Klaus
Klaus

Reputation: 25613

static_assert used in expression which is used in SFINAE context

If I use static_assert inside a condition for SFINAE, compiler emits an error and stops.

template < int i>
class X
{
    static_assert( i != 4 );
    public:
        static constexpr bool value = true;
};

    template < typename T >
typename std::enable_if< T::value, void>::type Do(  )
{
    std::cout << "one" << std::endl;
}

    template < typename T >
typename std::enable_if< !T::value, void>::type Do( )
{
    std::cout << "two" << std::endl;
}


int main()
{
    Do<std::true_type>();
    Do<std::false_type>();

    // ###########
    Do<X<1>>();
    Do<X<4>>();
}

Is this the behavior we should expect?

Upvotes: 3

Views: 129

Answers (1)

Is this the behavior we should expect?

Yes. The static assertion is in the instantiation of X, and not in the immediate context of of the template function. So it's not going to be mere substitution failure, the program will be ill-formed. There is a (albeit non-normative) note that further supports this should be this way.

[temp.deduct] (with note emphasized)

8 If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed, with a diagnostic required, if written using the substituted arguments. [ Note: If no diagnostic is required, the program is still ill-formed. Access checking is done as part of the substitution process.  — end note ] Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure. [ Note: The substitution into types and expressions can result in effects such as the instantiation of class template specializations and/or function template specializations, the generation of implicitly-defined functions, etc. Such effects are not in the “immediate context” and can result in the program being ill-formed. — end note ]

In your particular case, making X SFINAE friendly is also fairly straight forward:

// No static assertion
static constexpr bool value = (i != 4);

Or even

template <int i>
struct X : std::bool_constant< i != 4 >{};

Upvotes: 6

Related Questions