P0292R1 constexpr if已经included,正在进行C17 . 它似乎很有用(并且可以取代SFINAE的使用),但是有关 static_assert
格式错误的评论,假分支中不需要诊断让我感到害怕:
Disarming static_assert declarations in the non-taken branch of a
constexpr if is not proposed.
void f() {
if constexpr (false)
static_assert(false); // ill-formed
}
template<class T>
void g() {
if constexpr (false)
static_assert(false); // ill-formed; no
// diagnostic required for template definition
}
我认为完全禁止在constexpr中使用 static_assert
(至少是假/非分支,但实际上这意味着它不是一个安全或有用的东西) .
这是如何从标准文本中产生的?我在提案措辞中没有提到 static_assert
,而且C 14 constexpr函数允许 static_assert
(cppreference的详细信息:constexpr) .
是否隐藏在这个新句子中(6.4.1之后)? :
当constexpr if语句出现在模板化实体中时,在封闭模板或通用lambda的实例化期间,不会实例化丢弃的语句 .
从那以后,我假设它也被禁止,不需要诊断,调用调用图下面某处可能调用 static_assert
的其他constexpr(模板)函数 .
Bottom line:
如果我的理解是正确的,那么对于 constexpr if
的安全性和有用性是不是非常严格限制,因为我们必须知道(从文档或代码检查)有关 static_assert
的任何使用?我的担忧是否错位?
Update:
这段代码在没有警告的情况下编译(clang head 3.9.0)但是我的理解是不正确的,不需要诊断 . 是否有效?
template< typename T>
constexpr void other_library_foo(){
static_assert(std::is_same<T,int>::value);
}
template<class T>
void g() {
if constexpr (false)
other_library_foo<T>();
}
int main(){
g<float>();
g<int>();
}
2 回答
这是关于模板的完善规则 - 允许编译器诊断
template<class> void f() { return 1; }
的相同规则 . [temp.res]/8以新的变化加粗:无法为包含
static_assert
的模板生成有效的专业化,该模板的条件是非依赖的并且计算结果为false
,因此程序是格式错误的NDR .具有依赖条件的
static_assert
s可以评估至少一种类型的true
不受影响 .Edit: 我通过实例和更详细解释导致这些问题的误解来保持这种自我回答 . T.C.的简短回答是严格的 .
重新阅读提案并在current draft的
static_assert
上,我得出结论,我的担忧是错误的 . 首先,这里的重点应该放在模板定义上 .如果实例化模板,则按预期方式激活任何
static_assert
. 这可能与我引用的陈述很好地吻合:这对我来说有点模糊,但我得出结论,这意味着丢弃语句中出现的模板不会被实例化 . 但是其他代码必须在语法上有效 . 因此,当实例化包含
static_assert
的模板时,丢弃的if constexpr
子句中的static_assert(F)
,[其中F为假,字面或constexpr值]仍然是'bite' . 或者(不是必需的,在编译器的支配下)已经在声明中,如果已知它总是假的 .示例:(live demo)
static_assert
上的标准文字非常短 . 在标准中,这是一种通过诊断使程序格式错误的方法(正如@immibis也指出的那样):