Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a partial specialization refer to sizeof(T) in the specialization's argument list?

Tags:

c++

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?

like image 783
geza Avatar asked Apr 18 '20 17:04

geza


1 Answers

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.

like image 94
Jarod42 Avatar answered Nov 18 '22 15:11

Jarod42