Look at this simple code (godbolt):
template <typename, int>
struct Foo;
template <typename T>
struct Foo<T, (int)sizeof(T)>;
Clang compiles it, while gcc doesn't:
error: template argument '(int)(sizeof (T))' involves template parameter(s)
struct Foo<T, (int)sizeof(T)>;
^~~~~~~~~~~~~~
Which compiler is correct and why?
According to https://timsong-cpp.github.io/cppwp/n4140/temp.class.spec#8.1
A partially specialized non-type argument expression shall not involve a template parameter of the partial specialization except when the argument expression is a simple identifier.
sizeof(T)
is not a simple identifier.
So gcc is right.
Possible work around, if appropriate, is to replace non-type template parameter by a type (wrapping the constant):
template <typename, typename Size>
struct Foo;
template <typename T>
struct Foo<T, std::integral_constant<int, (int)sizeof(T)>>;
Demo
More recent version temp.class.spec#match-3 (after CWG1315) allows it:
If the template arguments of a partial specialization cannot be deduced because of the structure of its template-parameter-list and the template-id, the program is ill-formed. [ Example:
template <int I, int J> struct A {}; template <int I> struct A<I+5, I*2> {}; // error template <int I> struct A<I, I> {}; // OK template <int I, int J, int K> struct B {}; template <int I> struct B<I, I*2, 2> {}; // OK
— end example ]
So clang is right.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With