为何require-clause中无括号==表达式不通过但||表达式可通过?
为什么requires子句中
==表达式需要括号,而||不需要? 我了解到C++标准要求requires子句中的复杂表达式(含运算符的)需要加括号,但实际测试发现:用||的表达式无需括号就能被所有编译器接受,用==的却全被拒绝。测试代码如下:
template<typename T> struct C { constexpr static bool b = T{} + 1; constexpr static bool c = T{} + 1; }; // template<typename T> requires C<T>::b == C<T>::c void f(); // 所有编译器拒绝此代码 template<typename T> requires C<T>::b || C<T>::c void bar(); // 所有编译器接受此代码 int main() { // f<int>(); // 三款编译器均失败 bar<int>(); // 三款编译器均可行 }
原因解析
这是因为C++语法中requires子句的表达式优先级规则导致的:
requires关键字后直接跟的表达式,会被解析为*初级表达式(primary-expression)*的后续部分。==的优先级低于模板参数列表与requires子句的语法边界,编译器会错误地将C<T>::b ==中的==当成模板声明的一部分,而非表达式运算符,进而触发语法错误。- 而
||属于逻辑或运算符,虽然优先级更低,但编译器能明确识别它是逻辑表达式的起始——模板声明语法中不会出现||作为声明的一部分,因此可以正确将整个C<T>::b || C<T>::c解析为布尔表达式。
根据C++标准,requires子句中的表达式如果不是单个初级表达式(比如包含二元运算符的表达式),必须用括号明确包裹以避免语法歧义。||能通过是编译器的“宽容”解析,但严格来说,这类表达式都应该加括号,写成:
template<typename T> requires (C<T>::b == C<T>::c) void f(); template<typename T> requires (C<T>::b || C<T>::c) void bar();
这样才完全符合标准要求,不会出现编译兼容性问题。
内容的提问来源于stack exchange,提问作者user20562802
相关产品推荐
相关产品推荐

