Variadic template errors in struct template but not in function template

Why this code does not work?

template <size_t counter, typename TTag, typename Head, typename... Tails>
struct Tag2IDImpl {
  constexpr static int value = std::is_same_v<TTag, Head>? counter : Tag2IDImpl<counter+1, TTag, Tails...>::value;
};

template <typename TTag, typename... TParameters>
struct Tag2ID {
  constexpr static int value = Tag2IDImpl<0, TTag, TParameters...>::value;
};

struct A;
struct B;
struct C;
struct D;


int main() {
  std::cout<<Tag2ID<A, B, C, D,A>::value<<std::endl;
}

I got error like this:

vartypedict.cpp: In instantiation of ‘constexpr const int Tag2IDImpl<3, A, A>::value’:
vartypedict.cpp:39:109:   recursively required from ‘constexpr const int Tag2IDImpl<1, A, C, D, A>::value’
vartypedict.cpp:39:109:   required from ‘constexpr const int Tag2IDImpl<0, A, B, C, D, A>::value’
vartypedict.cpp:44:69:   required from ‘constexpr const int Tag2ID<A, B, C, D, A>::value’
vartypedict.cpp:97:36:   required from here
vartypedict.cpp:39:109: error: wrong number of template arguments (2, should be at least 3)
   39 |   constexpr static int value = std::is_same_v<TTag, Head>? counter : Tag2IDImpl<counter+1, TTag, Tails...>::value;
      |                                                                                                             ^~~~~
vartypedict.cpp:38:8: note: provided for ‘template<long unsigned int counter, class TTag, class Head, class ... Tails> struct Tag2IDImpl’
   38 | struct Tag2IDImpl {

If I use function template as follows, it works:

template <size_t counter, typename TTag, typename THead, typename...TTails>
constexpr size_t Tag2IDImpl() {
  if(std::is_same_v<TTag, THead>) {
    return counter;
  } else {
    if constexpr(sizeof...(TTails)>0) {
      return Tag2IDImpl<counter+1, TTag, TTails...>();
    } else {
      return counter+1;
    }
  }

}

template <typename TTag, typename... TParameters>
constexpr size_t Tag2ID() {
  return Tag2IDImpl<0, TTag, TParameters...>();
}

My question is why functional template recursive call "Tag2IDImpl<counter+1, TTag, TTails…>()" can match to the function template "template <size_t counter, typename TTag, typename THead, typename…TTails>", which using struct, it complains mismatch?

Source: Windows Questions C++

LEAVE A COMMENT