这是关于模板的完善规则 - 允许编译器诊断的相同规则 template<class> void f() { return 1; } 。 [temp.res] / 8 随着新的变化加粗:
template<class> void f() { return 1; }
如果出现以下情况,该计划格式错误,无需诊断: 无法为模板生成有效的专业化 的 或者一个子语句 一个 constexpr if 声明([stmt.if])在一个 模板 强> 并且模板未实例化,或 [...]
如果出现以下情况,该计划格式错误,无需诊断:
constexpr if
无法为包含的模板生成有效的专业化 static_assert 其状况是非依赖性的并且评估为 false ,所以该计划是不正常的NDR。
static_assert
false
static_assert s具有可以评估的依赖条件 true 至少一种类型不受影响。
true
的 编辑: 强> 我通过实例和更详细解释导致这些问题的误解来保持这种自我回答。 T.C.的简短回答是严格的。
重新阅读提案之后 static_assert 在里面 目前的草案 我得出的结论是,我的担忧是错误的。首先,这里的重点应放在模板上 定义 。
形成不良;模板定义无需诊断
如果是模板 实例化 , 任何 static_assert 火如预期。这可能与我引用的陈述很好地吻合:
...丢弃的语句未实例化。
这对我来说有点模糊,但我的结论是,这意味着 模板 在丢弃的语句中发生的将不会被实例化。其他代码 但必须在语法上有效。一个 static_assert(F) ,[其中F是假的,字面上或constexpr值]在丢弃的内部 if constexpr 因此,当包含模板的模板时,子句仍会“咬” static_assert 被实例化。或者(不是必需的,由编译器支配)已经在声明中,如果它已知总是为假。
static_assert(F)
if constexpr
例子: ( 现场演示 )
#include <type_traits> template< typename T> constexpr void some_library_foo(){ static_assert(std::is_same<T,int>::value); } template< typename T> constexpr void other_library_bar(){ static_assert(std::is_same<T,float>::value); } template< typename T> constexpr void buzz(){ // This template is ill-formated, (invalid) no diagnostic required, // since there are no T which could make it valid. (As also mentioned // in the answer by T.C.). // That also means that neither of these are required to fire, but // clang does (and very likely all compilers for similar cases), at // least when buzz is instantiated. static_assert(! std::is_same<T,T>::value); static_assert(false); // does fire already at declaration // with latest version of clang } template<class T, bool IntCase> void g() { if constexpr (IntCase){ some_library_foo<T>(); // Both two static asserts will fire even though within if constexpr: static_assert(!IntCase) ; // ill-formated diagnostic required if // IntCase is true static_assert(IntCase) ; // ill-formated diagnostic required if // IntCase is false // However, don't do this: static_assert(false) ; // ill-formated, no diagnostic required, // for the same reasons as with buzz(). } else { other_library_bar<T>(); } } int main(){ g<int,true>(); g<float,false>(); //g<int,false>(); // ill-formated, diagnostic required //g<float,true>(); // ill-formated, diagnostic required }
关于标准文本 static_assert 非常短。在标准中,它是制作程序的一种方式 病态的 诊断(如@immibis也指出):
7.6 ...如果转换后的表达式的值为true,则声明无效。否则,该程序是不正确的,并且 得到的诊断消息(1.4)应包括文本 string-literal,如果提供了一个......