9

Providing a static_assert in templates are often helpful. In the case where a template shouldn't be instantiated in a certain way at all, I often do this

template<typename T, typename = void>
struct S
{
    static_assert(false, "Unconditional error");
    static_assert(sizeof(T) != sizeof(T), "Error on instantiation");
};

template<typename T>
struct S<T, std::enable_if_t<std::is_integral_v<T>>>
{
    // ...
};

The first static_assert will fail instantly, even without an instantiation of S, while the second will succeed if no instantiations will result in the primary template.

The second static_assert is obviously a tautology, but it "depends" on T such that the intended effect is achieved. But is this guaranteed? Are compilers allowed to evaluate these tautologies?

Passer By
  • 19,325
  • 6
  • 49
  • 96
  • But there may not be such a specialization defined and the compiler doesn't have to be aware about the future code while processing anti-tautology... – W.F. Jun 03 '17 at 16:30
  • IMHO the same part of code can't be at the same time well and ill formed depending on (possibly distant) context... It would make additional difficulty for the already heavily loaded compiler... – W.F. Jun 03 '17 at 18:05
  • @bolov If only I could close the question now :( – Passer By Dec 05 '17 at 16:11

1 Answers1

10

The relevant rule is [temp.res]/8:

Knowing which names are type names allows the syntax of every template to be checked. The program is ill-formed, no diagnostic required, if:

  • no valid specialization can be generated for a template or a substatement of a constexpr if statement within a template and the template is not instantiated, or

  • [...]

Both static_asserts in the example cause the program to be ill-formed, but no diagnostic is required. Compilers are certainly allowed to evaluate arbitrarily complex expressions to attempt to prove that no valid specialization could be generated, but they are not required that they do so. false is certainly an easy case to immediately verify, so it's not surprising that it is diagnosed.


A common approach to the desire to always issue a diagnostic is:

// never specialize me!
template <typename T>
struct always_false : std::false_type { };

template <typename T>
constexpr bool always_false_v = always_false<T>::value;

template<typename T, typename = void>
struct S {
    static_assert(always_false_v<T>, "Unconditional error");
};

always_false could hypothetically be specialized on a particular T to yield true_type, so there could hypothetically be a valid specialization S<T>. But don't let anybody actually do that.

Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977
  • This is what I'm afraid of. I suppose it is ill-advised to write stuff like this unless you are a compiler writer? – Passer By Dec 05 '17 at 15:26
  • 2
    Wait, _"no valid specialization can be generated for a template"_, doesn't that refer to "no `T` exists such that `S` is valid"? But in in the example `S` is valid and therefore the program is well-formed? – Passer By Dec 05 '17 at 15:32
  • @PasserBy: This post is very relevant to yours: https://stackoverflow.com/questions/5246049/c11-static-assert-and-template-instantiation – AndyG Dec 05 '17 at 15:56
  • 1
    @PasserBy no. This sentence refers to the hypothetical instantiations of the main template, without taking into account specializations. There are two answers an extended discussions about this in the duplicate I linked. – bolov Dec 05 '17 at 16:03