Tag2ID is giving me trouble


Hi,
I am trying to create a metafunction that returns the index of a type in a list of types (Tag2ID) but am having trouble:





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<typename Tag, size_t P, size_t N, typename ... T>
struct Tag2IDHelper;


template<typename Tag, size_t N, typename T>
struct Tag2IDHelper<Tag, N, N, T>
{
	constexpr static size_t Pos = std::is_same_v<Tag, T> ? N - 1 : -1;
};


template<typename Tag, size_t P, size_t N, typename Head, typename... Tail>
struct Tag2IDHelper<Tag, P, N, Head, Tail...>
{
	constexpr static size_t Pos = std::is_same<Tag, Head>::value ? P : Tag2IDHelper<Tag, P + 1, N, Tail...>::Pos;
};



1
2
3
4
5
template<typename Tag, typename...T>
struct Tag2ID
{
	constexpr static size_t Pos = Tag2IDHelper<Tag, 0, sizeof...(T), T...>::Pos;
};



any ideas?

Regards
1
2
3
4
5
6
7
8
template <typename Tag, typename Head, typename... Tail>
  constexpr int Tag2ID()
  { 
    if constexpr (sizeof...(Tail)) 
      return std::is_same_v<Tag, Head>? 0: 1 + Tag2ID<Tag, Tail...>();
    else 
      return 1;
  }
Last edited on
What happens when Tag is NOT part of (Head,Tail...)? What index does Tag2ID() return?


1
2
3
4
5
struct A;
struct B;
struct C;
struct D;
constexpr size_t pos = Tag2ID<D, A, B, C>();

What happens when Tag is NOT part of (Head,Tail...)? What index does Tag2ID() return?

It returns the length of the list being searched, 1 + sizeof...(Tail). For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <type_traits>

template <typename Tag, typename Head, typename... Tail>
  constexpr int Tag2ID()
  { 
    if constexpr (sizeof...(Tail)) 
      return std::is_same_v<Tag, Head>? 0: 1 + Tag2ID<Tag, Tail...>();
    else 
      return 1;
  }
  
int main()
{
  struct A {}; 
  struct B {};
  struct C {};
  struct D {};

  static_assert(Tag2ID<D, A, B, C>() == 3);
}
Last edited on
To behave like that we need to change the code to:

1
2
3
4
5
6
7
8
9
	template <typename Tag, typename Head, typename... Tail>
	constexpr size_t Tag2ID()
	{
		if constexpr (sizeof...(Tail))
			return std::is_same_v<Tag, Head> ? 0 : 1 + Tag2ID<Tag, Tail...>();
		else
			return std::is_same_v<Tag, Head> ? 0 : 1;
	}


else when we ask for the position of the last type in the list, it will return the length of the list:

1
2
	constexpr size_t pos = Tag2ID<C, A, B, C>();
        static_assert(pos == 3);


instead of the correct value 2!!
You're right, thank you.
Topic archived. No new replies allowed.