2

I wanted to know if a variable can be equal to a type (here it's the magic_type)

#include <typeinfo>

template<typename T>
class C
{
public:
   magic_type t;
   t list;
   T data;

   C(void)
   {
      if (typeid(data) == typeid(int))
         t = float; // so typeid(list) = typedid(float)
      else
         t = int; // and typeid(list) = typedid(int)
   }
};
JeJo
  • 30,635
  • 6
  • 49
  • 88
  • 1
    Types don't exist per se at runtime. Can you elaborate on why you need "type variables" and why templates don't meet your requirements? – Brian61354270 Jun 24 '20 at 16:44
  • A variable cannot be equal to a type. The *type* is a property of the variable, mainly used by the compiler. – Thomas Matthews Jun 24 '20 at 16:44
  • 1
    Not sure what the use case would be, but if you want to set a flag indicating what type a variable is, you can use an enum. Something like: `enum VariableTypes { FLOAT, INT }` and declare `t` of type `enum VariableTypes`. – Jonathan Lam Jun 24 '20 at 16:45
  • ah okay too bad thanks ^^ –  Jun 24 '20 at 16:46
  • You can use templates for functions as well. You can also overload functions (without templates). The compiler will pick the correct function based on the parameter types. – Thomas Matthews Jun 24 '20 at 16:47
  • See also: [Why does C++ not have reflection?](https://stackoverflow.com/questions/359237) – Jonathan Lam Jun 24 '20 at 16:47
  • 1
    You don't need `magic_type t;` because you already have it: `T`. Change `t list;` to `T list;`. In C++, an empty parameter list is idiomatically given as `C()` rather than `C(void)`. – Eljay Jun 24 '20 at 16:49
  • 2
    do you really want `t` to be `float` when `T` is `int` or is this a typo? – 463035818_is_not_an_ai Jun 24 '20 at 16:50
  • Isn't the answer [`std::type_info`](https://en.cppreference.com/w/cpp/types/type_info)? (But also don't do this, use `std::conditional` and templates) – Mooing Duck Jun 24 '20 at 16:54

2 Answers2

6

If you want the magic_type be float when T == int and otherwise float, use std::conditional_t. This will resolve the magic_type at compile time.

In order to check whether two types are the same, you could use std::is_same_v. Include <type_traits>, for both of the trait's usage.

#include <type_traits>  // std::conditional_t, std::is_same_v

template<typename T>
class C
{
   // type alias
   using magic_type = std::conditional_t<std::is_same_v<T, int>, float, int>;

   magic_type t;  // now `magic_type` == `float` if `T` == `int`, otherwise `float`
   T data;

public:       
   // ... code
};
JeJo
  • 30,635
  • 6
  • 49
  • 88
  • All right, thank you very much. ^^ And if I have other conditions, how can I add them if(typeid(data) == typeid(string)), if(typeid(data) == typeid(bool)), etc.? –  Jun 24 '20 at 16:53
  • 1
    @user13286774 The same way demonstrated above. For example for `std::string`, you could `std::conditional_t, /* true type*/, /*false type*/>;` – JeJo Jun 24 '20 at 16:57
  • Yeah i get it ^^. But can we use more than two types ? –  Jun 24 '20 at 17:00
  • @user13286774 *use more than two types* for example? Do you mean checking more types together: `using magic_type = std::conditional_t || std::is_same_v, float, int>;`? – JeJo Jun 24 '20 at 17:02
2

A general way to do this without nesting and keeping the logic code more familiar is with an if constexpr helper:

// Not needed if you know you can default-construct every type.
template<typename T>
struct type_t {
    using type = T;
};

static auto get_list_type() {
    if constexpr (std::is_same_v<T, int>) {
        return type_t<float>{};
    } else if constexpr (std::is_same_v<T, float>) {
        return type_t<int>{};
    } else if constexpr (...) {
         return ...;
    } else {
        return ...;
    }
}

typename decltype(get_list_type())::type list; // no typename in C++20

If you're so inclined, there are also a couple compile-time switch libraries out there.

chris
  • 60,560
  • 13
  • 143
  • 205