如果 constexpr 和相关的 false static_assert 格式不正确?

sea*_*lus 4 c++ language-lawyer

相关的问题提供了一种类型无关的例子falsestatic_assert

template<class T> void foo()
{
    if constexpr(false)
        static_assert(false);
}
Run Code Online (Sandbox Code Playgroud)

但是,我更担心同样的事情是否适用于依赖于类型的false. 这是标准中的相关引用:

如果不能为模板或模板中的 constexpr if 语句的子语句生成有效的特化,并且模板未实例化,则程序格式错误,无需诊断§ 13.7/8.1

这让我感到惊讶,因为我经常看到以下习语:

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

事实上,cppreference 甚至提供了一个同样的例子

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

根据我的理解,在这两种情况下,都无法为相关if constexpr子语句生成有效的专业化,因此格式不正确,不需要诊断。我对么?

Hol*_*Cat 5

无法为相关if constexpr子语句生成有效的专业化

嗯,没有。

如果您dependent_false先进行专业化,则可以拥有该分支的有效专业化:

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

可以创建这样的专业化(即使您没有)这一事实使static_assert(dependent_false<T>::value);格式良好。

另一方面,static_assert(!std::is_same_v<T, T>);是格式错误的 NDR,因为std::不允许专门化模板。