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

时间:2018-09-02 12:48:41

标签: c++ language-lawyer template-specialization static-assert

以下代码可以正常编译:

#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

2 个答案:

答案 0 :(得分:6)

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

  

[temp.expl.spec]/5

     

显式专门类的成员不是隐式的   从类模板的成员声明实例化;   相反,类模板专门化的成员应自己   如果需要定义,则进行明确定义。在这种情况下,   类模板的定义显式专业化应在   定义成员时的范围。 的定义   显式专门类与a的定义无关   产生了专业化。也就是说,其成员不必具有相同的   名称,类型等作为生成的专业化的成员。   显式专门的类模板的成员在   与普通类成员的方式相同,但不使用template <>   语法。在显式定义成员时也是如此   专业会员班。但是,template <>用于定义   一个显式专门的成员类模板的成员,该模板是   专门用作类模板。

专业化就像常规课程一样。它不是模板,没有任何依赖。因此dependent_false<X>::value只是一个常量表达式,其立即求值为false。因此,静态断言会立即触发。

答案 1 :(得分:0)

即使未实例化的模板部件也应该是有效的C ++代码。 static_assert(false)使程序格式错误。因此,您可以使用static_assert来进行专业化,而在编译时就知道false,并且程序会变得格式错误。您的类上没有任何未解析的模板参数,这些参数在static_assert中使用,使编译器感到疑惑。它确切知道它是false

if constexpr也是如此,即使static_assert所在的部分总是被丢弃,也不能对已知为假的表达式使用static_assert