Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are compilers allowed to evaluate tautologies in static assert [duplicate]

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?

like image 883
Passer By Avatar asked Jun 03 '17 14:06

Passer By


1 Answers

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.

like image 189
Barry Avatar answered Oct 19 '22 15:10

Barry