GCC与Clang、MSVC在使用永真concept实现自定义concept的行为差异
GCC 11.2的该编译行为不符合C++标准
Clang、MSVC的编译结果符合标准要求,refable<void>按照标准应当求值为false,static_assert理应编译失败。
问题复现代码
template <typename...> concept always_true = true; template <typename T> concept refable = always_true<T&>; static_assert(refable<void>);
标准规则说明
- 检查概念约束是否满足时,需要先将模板实参完整代入约束表达式:当替换过程中在直接上下文中出现非法构造(比如此处试图生成
void&这种C++不允许的类型),不会触发硬编译错误,而是直接判定该约束不满足,求值结果为false。 - 本例中
refable<T>的约束表达式是always_true<T&>,当T为void时,第一步就要构造T&即void&,该错误属于约束替换的直接上下文错误,因此refable<void>直接判定为false,static_assert必然失败。
GCC编译通过的原因
该现象是GCC 11.2实现C++20概念时的已知缺陷:当约束子表达式为模板名<实参>形式时,如果目标模板的常量值不依赖实参内容(本例always_true无论传入什么类型都固定为true),GCC会跳过对实参合法性的检查,直接取模板的常量值作为约束结果,违反了标准要求的完整替换检查流程。该缺陷在后续更高版本的GCC中已经得到修复。
内容的提问来源于stack exchange,提问作者whatishappened
相关产品推荐
相关产品推荐

