1

I want to be able to generate a number for each type of a particular typelist.

i.e. for the following 2 typelists (where Group works like std::variant):

class myclass; using GroupA = Group<int, double, myclass>; static_assert( GroupA::type_number<int> == 0 ); static_assert( GroupA::type_number<double> == 1 ); static_assert( GroupA::type_number<myclass> == 2 ); using GroupB = Group<double, myclass>; // different group => different numbering static_assert( GroupB::type_number<double> == 0 ); static_assert( GroupB::type_number<myclass> == 1 ); 

I tried to recurse through the Types, but I cannot end up with one template parameter on every type

template < typename ... Types> struct Group { template < typename T > constexpr static int type_number = 0; template < typename T, typename ... Types > constexpr static int type_number = type_number<Types...> + 1; }; 

I am imitating any/variant and I want to be able to sort a vector of them.

5
  • There are a number of fundamental C++ reasons why this is un-possible. Especially if you want a constexpr type_number. Just conduct a simple thought experiment yourself. Put two of these types in different header files. No translation unit #includes both of them. Or they are #included in different order. How do you expect to achieve a consistent type_number for each one of the two types? Commented Apr 25, 2021 at 23:46
  • How should sorting work for incomparable types? Commented Apr 25, 2021 at 23:50
  • 1
    Note that std::type_index might be the best tool here Commented Apr 25, 2021 at 23:52
  • @alterigel, good idea, but I need something that will work the same way between different compilers/operating systems. I think type_info does not guarantee that, does it? Commented Apr 25, 2021 at 23:56
  • @alterigel, (about sorting between incomparable types) : I plan to make a vector of type-erased objects, sharing a get_type_number() function. I will sort it using this type_number first. If they are the same type, I can then compare them the normal way. Commented Apr 25, 2021 at 23:59

2 Answers 2

3

Something along these lines:

template <typename T, typename Head, typename ... Tail> constexpr int TypeNumber(int start) { if constexpr (std::is_same_v<T, Head>) { return start; } else { return TypeNumber<T, Tail...>(start + 1); } } template < typename ... Types> struct Group { template < typename T > constexpr static int type_number = TypeNumber<T, Types...>(0); }; 

Demo

Sign up to request clarification or add additional context in comments.

2 Comments

(+1) For C++11 I replaced std::is_same_v<T,Head> with std::is_same<T,Head>::value. But C++11 does not have constexpr if. Should I use the ternary operator (pred?true:false) to get around this?
Ternary operator won't work, since both halves of it get instantiated (ask me how I know). In C++11, you'd need partial specialization. In any case, C++11 doesn't have template variables, so you can't have GroupA::type_number<int> syntax to begin with.
1

Recursive way make code longer to compile. Trick is to use pairing from the start,

Then, you can use overload to "select" the Pair by index or by type (doublon would cause ambiguous call).

template <typename T, std::size_t I> struct Pair { // possibly data, as `T data;` for tuple }; template <typename T, std::size_t I> constexpr std::integral_constant<std::size_t, I> type_number(Pair<T, I>) { return {}; } template <typename Seq, typename ... Ts> struct GroupImpl; template <std::size_t ... Is, typename ... Ts> struct GroupImpl<std::index_sequence<Is...>, Ts...> : Pair<Ts, Is>... { template <typename T> constexpr static auto type_number() { return decltype(::type_number<T>(GroupImpl{})){}; } }; template <typename ... Ts> using Group = GroupImpl<std::make_index_sequence<sizeof...(Ts)>, Ts...>; 

Demo

std::index_sequence is not C++11, but can be implemented in C++11 (linearly or even logarithmically in number of instantiation) (in C++14, in std, compiler might even use intrinsic to have only one instantiation :-) )

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.