Search code examples
c++templatesstatic-assert

static_assert in not initialized template class with valid specialization


My question is, whether the following code is valid:

template<int i> class Class
{
    static_assert(sizeof(i) == 0, "Class instantiated with i != 1");
};

template<> class Class<1> {};

This snippet compiles with g++. But clang++ is trapped by the static_assert:

error: static_assert failed "Class instantiated with non-int type"

A template that uses a type instead of an int like

template<typename T> class Class
{
    static_assert(sizeof(T) == 0, "Class instantiated with non-int type");
};

template<> class Class<int> {};

is accepted by both compilers. Exactly the same pattern applies to function templates.

I found open-std.org::Non-dependent static_assert-declarations, but that does not seem to apply, because my static_assert is dependent on the template parameter.

You may check the described behavior on godbolt.org

EDIT: As Johan Lundberg points out in the comment my question is wrong. Indeed sizeof(i) does not depend on the template parameter. Also R.Sahu is completely right: It would make much more sense to assert i != 1. For this again both compilers accept the code.

However, still the upper example compiles with g++. As open-std.org::Non-dependent static_assert-declarations applies to that case (I apologize again for the wrong question in this respect): Is g++ actually wrong in compiling the code without error?


Solution

  • clang++ is right to reject your code, but g++ is not wrong to fail to catch the error; this is a "no diagnostic required" situation.

    The Standard strictly defines expressions within a template as "type-dependent" and/or "value-dependent". Given template<int i>, i is value-dependent but not type-dependent.

    [14.6.2.2/4]: Expressions of the following forms are never type-dependent (because the type of the expression cannot be dependent):

    • ...
    • sizeof unary-expression
    • ...

    [14.6.2.3/2]: Expressions of the following form are value-dependent if the unary-expression or expression is type-dependent or the type-id is dependent:

    • sizeof unary-expression
    • ...

    So sizeof(i) is not dependent.

    Finally, 14.6/8 says:

    If a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, the program is ill-formed; no diagnostic is required.