处理IFNDR表达式时,static_assert是否必须触发编译失败?
IFNDR场景下static_assert的编译行为解析
核心疑问
当处理**ill-formed-no-diagnostic-required(IFNDR,格式错误但无需强制诊断)**表达式时,static_assert是否必须触发编译失败?还是编译器可依据“无需诊断”规则忽略该表达式,让static_assert成功通过?
示例代码与编译器行为差异
以下代码包含两处IFNDR场景,不同编译器对static_assert的处理结果存在明显分歧:
template<typename T> concept A = T::value || true; template<typename U> concept B = A<U*>; template<typename V> concept C = A<V&>; int main(){ static_assert(B<int&>); // Clang、MSVC拒绝编译,GCC接受;表达式非法(指向引用的指针int&*不存在) static_assert(C<void>); // Clang、MSVC拒绝编译,GCC接受;表达式非法(void的引用void&不存在) }
标准规则与行为逻辑
根据C++标准对IFNDR的定义:这类代码属于格式错误,但编译器不被强制要求输出诊断信息。针对static_assert的断言表达式处于IFNDR场景时,编译器拥有灵活处理的空间:
- 一种选择是检测到非法表达式,触发
static_assert的编译失败(如Clang、MSVC的行为); - 另一种选择是忽略该非法表达式的诊断要求,将
static_assert判定为通过(如GCC的行为)。
这种差异的核心原因是:概念约束归一化过程中,展开约束产生非法类型的情况被归为IFNDR范畴,标准赋予了编译器自主选择是否报错的权限,两种行为均符合标准要求。
内容的提问来源于stack exchange,提问作者Amir Kirsh
相关产品推荐
相关产品推荐

