关于函数f:模板变量b的非类型模板实参替换约束表达式是否为有效常量表达式?
C++20约束表达式中非类型模板实参的有效性问题
代码示例
struct s { static constexpr bool v = true; }; template<auto> inline constexpr bool b = true; constexpr bool f(auto x) requires b<x.v> { return true; } static_assert(f(s{})); // clang 编译通过,gcc 报错,msvc 编译通过
GCC错误信息
<source>:3:36: error: missing template arguments before '<' token 3 | constexpr bool f(auto x) requires b<x.v> { return true; } | ^ <source>:3:36: error: expected initializer before '<' token <source>:4:15: error: 'f' was not declared in this scope 4 | static_assert(f(s{})); | ^
问题解答
1. 该约束表达式是否为有效常量表达式?
是。当调用f(s{})时,函数参数x的类型为s,x.v引用的是s的静态constexpr成员变量,本身就是合法的常量表达式。用它作为非类型模板实参实例化模板变量b后,b<x.v>是值为true的常量表达式,完全满足约束要求。
2. C++20标准中的具体依据
根据C++20标准的 [temp.constr.atomic]/3 条款:
原子约束被满足的条件是,给定偏特化的模板实参,对应的谓词被满足。对于作为表达式的谓词,该表达式必须是求值为true的常量表达式。
同时,标准 [expr.const]/13 明确静态constexpr成员变量属于允许作为常量表达式结果的实体,因此x.v可以合法地作为非类型模板实参,进而b<x.v>成为符合要求的常量表达式约束。
GCC的报错属于编译器实现bug,clang和msvc的处理符合标准要求。
内容的提问来源于stack exchange,提问作者303
相关产品推荐
相关产品推荐

