模板特化中的静态断言即使未实例化也会失败

Static assert in template specialization fails even if it is not instantiated

以下代码可以正常编译:

#include <type_traits>

template <typename T> struct dependent_true : std::true_type { };
template <typename T> struct dependent_false : std::false_type { };

template <bool B = false>
class X { static_assert(dependent_false<X>::value); };

template <>
class X<true> { static_assert(dependent_true<X>::value); };

int main() {
   X<true> x;
}

即主模板中的static_assert不计算。相反,如果我切换到:

template <bool B = false>
class X { static_assert(dependent_true<X>::value); };

template <>
class X<true> { static_assert(dependent_false<X>::value); };

int main() {
    X<false> x;
}

然后,模板特化中的静态断言失败,即使它没有被实例化。 我只是想知道为什么。 我在 GCC 8 和 Clang 6 (-std=c++17) 中观察到这种行为。

现场演示:https://wandbox.org/permlink/MOWNLnGMgmuDA2Ht

即使是非实例化的模板部分也应该是有效的 C++ 代码。 static_assert(false) 使程序格式错误。因此,您的专业化 static_assert 在编译时已知为 false 并且您的程序格式错误。你的 class 上没有未解析的模板参数,它在 static_assert 中使用,使编译器感到奇怪;它确切地知道它是 false

if constexpr 也是如此,你也不能将 static_assert 与已知为假的表达式一起使用,即使这个 static_assert 所在的部分总是被丢弃。

template <> class X<true> {/* ... */}; - 不再是模板。

[temp.expl.spec]/5

A member of an explicitly specialized class is not implicitly instantiated from the member declaration of the class template; instead, the member of the class template specialization shall itself be explicitly defined if its definition is required. In this case, the definition of the class template explicit specialization shall be in scope at the point at which the member is defined. The definition of an explicitly specialized class is unrelated to the definition of a generated specialization. That is, its members need not have the same names, types, etc. as the members of a generated specialization. Members of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntax. The same is true when defining a member of an explicitly specialized member class. However, template<> is used in defining a member of an explicitly specialized member class template that is specialized as a class template.

专业化就像一个普通的 class。它不是模板,没有任何依赖。因此 dependent_false<X>::value 只是一个立即求值为 false 的常量表达式。所以立即触发静态断言。