Home > Net >  Accessing templatized static constexpr member of templatized class with template parameter
Accessing templatized static constexpr member of templatized class with template parameter

Time:08-22

So I've got a templatized class which has a templatized static constexpr bool. The setup boils down to this:

#include <type_traits>

template <typename T>
class A {
public:
  template <typename U>
  static constexpr bool same = std::is_same_v<T, U>;
};

template <typename T>
bool test() {
  return A<T>::same<int>; // errors
}

int main() {
  A<int>::same<int>;      // compiles perfectly
  test<int>();            // errors
}

When I access it with actual types like A<int>::same<int>, it compiles just fine, but when I try to access it with a template type, as in the test() function above, it errors. Here is the full list of errors:

constexpr_value.cpp: In function ‘bool test()’:
constexpr_value.cpp:12:21: error: expected primary-expression before ‘int’
   12 |   return A<T>::same<int>;
      |                     ^~~
constexpr_value.cpp:12:21: error: expected ‘;’ before ‘int’
   12 |   return A<T>::same<int>;
      |                     ^~~
      |                     ;
constexpr_value.cpp:12:24: error: expected unqualified-id before ‘>’ token
   12 |   return A<T>::same<int>;
      |                        ^
constexpr_value.cpp: In instantiation of ‘bool test() [with T = int]’:
constexpr_value.cpp:16:12:   required from here
constexpr_value.cpp:12:16: error: ‘A<int>::same<U>’ missing template arguments
   12 |   return A<T>::same<int>;
      |                ^~~~

The first three errors are from the template itself, and they show up even when I don't use the test() function at all, so it seems like the compiler is assuming A<T>::same<int> is an invalid statement before even checking any specific Ts.

I don't understand these errors at all. Why does A<int>::same<int> compile perfectly, but as soon as you use template types, it doesn't like it at all? I don't even know where to begin fixing this, because the errors tell me nothing. The only difference between compiling and not is using <T> instead of <int>, so is there something I can do with T to tell the compiler that this is a valid statement?

CodePudding user response:

The template code is not equivalent to A<int>::same<int>. This will also compile:

template <typename T>
bool test() {
  return A<int>::same<int>;
}

Returning to the erroneous code. The latest GCC 12.1 would produce the hint in the warning:

constexpr_value.cpp: In function 'bool test()':
constexpr_value.cpp:12:16: warning: expected 'template' keyword before dependent template name [-Wmissing-template-keyword]
   12 |   return A<T>::same<int>; // errors
      |                ^~~~

As the warning message suggests the fix:

template <typename T>
bool test() {
  return A<T>::template same<int>;
}
//             ^^^^^^^^

See the hot question Where and why do I have to put the "template" and "typename" keywords? for more info.

  • Related