static_assert 用于 SFINAE 上下文中使用的表达式

static_assert used in expression which is used in SFINAE context

如果我在 SFINAE 的条件中使用 static_assert,编译器会发出错误并停止。

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?

是的。静态断言在 X 的实例化中,而不是在模板函数的直接上下文中。所以这不仅仅是替换失败,程序将是错误的。有一个(尽管是非规范的)说明,进一步支持应该是这样的。

[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 ]

在您的特定情况下,使 X SFINAE 友好也相当简单:

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

甚至

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