Search code examples
c++templatesc++11assertionsstatic-assert

static_assert fails check on templated object pointer


template <size_t N>
class Foo
{
    static_assert(N > 0, "WRONG");
    //void Something() = 0; //my original implementation
};

int main() {

    Foo<0> *p2 = nullptr;   //no error
    Foo<0> p;   //gives an error

    return 0;
}

I've tested both the lines separately. static_assert is not called when p2 is initialized but it is called and does indeed fail on p. Is this intended? (I've tried it on gcc, clang and VC)

What are the workarounds? Since I'm using abstract templated classes, it would be a nightmare if the assertion is only performed when a non-pointer object is instantiated. I can use a factory but that isn't exactly a proper solution.


Solution

  • You assuredly saw this quote from §14.7.1/1:

    Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3), the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program.

    Pointer types do not require their pointee to be a complete type (e.g. void* is an example of this). Thus the first line will not instantiate the specialization, but the second one needs to, hence the assertion fires only on that one.

    This is also addressed by an example three paragraphs further down:

    [ Example:

    template<class T> struct Z {
      void f();
      void g();
    };
    
    void h() {
      Z<int> a;      // instantiation of class Z<int> required
      Z<double>* q;  // instantiation of class Z<double> not required
      //[…]
    }
    

    Nothing in this example requires class Z<double> […] to be implicitly instantiated. — end example ]