Search code examples
c++templatesc++11language-lawyerstatic-assert

static_assert with dependent expression that is actually independent


Consider the following template:

template <typename T>
void foo() {
  static_assert(sizeof(T) == 0, "Now what?");
}

The standard (§7.4) says:

[If the condition to static_assert is false] the program is ill-formed, and the resulting diagnostic message (1.4) shall include the text of the string-literal, […]

(Reference taken from https://stackoverflow.com/a/11048906/560450)

In practice, the static_assert will not fail until we instantiate the function template foo, because the use othe the template parameter forces the compiler to evalute the condition only during two-phase lookup. Therefore, the code snippet above is not deemed ill-formed unless the function template is instantiated.

On the other hand, sizeof(T) > 0 in C++ by definition. Therefore, the value of the condition is in fact independent of any template parameter! Is a "malicious" compiler allowed to take advantage of this fact, and reject the program as ill-formed, regardless whether foo is actually instantiated or not?


Solution

  • Yes, the compiler is allowed, but not required, to reject this.

    §14.6 [temp.res]/p8:

    If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required.

    An easy workaround:

    template <typename T>
    struct foo_protector : std::false_type {};
    
    template <typename T>
    void foo() {
      static_assert(foo_protector<T>::value, "Now what?");
    }
    

    The compiler is not allowed to reject foo()'s definition because there might be a specialization of foo_protector, not yet seen, such that its value member is true. As long as you don't actually write such a specialization, the static_assert will fire as expected.