seaplusplus
seaplusplus

Reputation: 153

if constexpr and dependent false static_assert is ill formed?

A related question provides the example of a type-independent false in a static_assert:

template<class T> void foo()
{
    if constexpr(false)
        static_assert(false);
}

However, I am more concerned if the same thing applies to a type-dependent false. Here is the relevant quote from the standard:

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. § 13.7/8.1

This comes as a surprise to me as I frequently see the following idiom:

template<class T> void foo()
{
    if constexpr(cond)
        // ...
    else
        static_assert(!std::is_same_v<T, T>);
}

In fact, cppreference even provides an example of the same thing:

template<class T> struct dependent_false : std::false_type {};
template<class T> void foo()
{
    if constexpr (cond)
        // ...
    else
        static_assert(dependent_false<T>::value);
}

From my understanding, in both of these cases, no valid specialization can ever be generated for the relevant if constexpr substatements, and are therefore ill-formed, no diagnostic required. Am I correct?

Upvotes: 4

Views: 854

Answers (1)

HolyBlackCat
HolyBlackCat

Reputation: 96013

no valid specialization can ever be generated for the relevant if constexpr substatements

Well no.

You could have a valid specialization of that branch if you specialized dependent_false first:

template <> struct dependent_false<int> : std::true_type {};
///
foo<int>(); // <-- A valid specialization for the `else` branch is possible here

The fact that it's possible to create such a specialization (even if you don't have one) makes static_assert(dependent_false<T>::value); well-formed.

On the other hand, static_assert(!std::is_same_v<T, T>); is ill-formed NDR, because specializing templates from std:: is not allowed.

Upvotes: 5

Related Questions