为什么 requires 子句中的否定表达式需要括号?
Why are parentheses needed around negated expressions in a requires-clause?
以下代码是requires
子句的用法示例:
#include <type_traits>
template <typename T>
requires std::is_integral_v<T>
void take_integral(T value);
它接受一个计算为 bool
值(在本例中为 std::is_integral_v<T>
)的表达式,并按预期工作。
但是,当使用 !
运算符对此类表达式取反时,会导致编译错误:
#include <type_traits>
template <typename T>
requires !std::is_integral_v<T>
void take_integral(T value);
来自 GCC 的诊断:
<source>:4:12: error: expression must be enclosed in parentheses
4 | requires !std::is_integral_v<T>
| ^~~~~~~~~~~~~~~~~~~~~~
| ( )
Compiler returned: 1
来自 Clang 的诊断:
<source>:4:12: error: parentheses are required around this expression in a requires clause
requires !std::is_integral_v<T>
^~~~~~~~~~~~~~~~~~~~~~
( )
1 error generated.
Compiler returned: 1
这里为什么需要括号?
括号是必需的,因为它们避免了语言解析歧义。
并非每个表达式都允许在 requires
子句中。事实上,该标准给出了一个示例,说明如果允许所有表达式,将如何出现解析歧义:
[...] The expression in a requires-clause uses a restricted grammar to avoid ambiguities.
Parentheses can be used to specify arbitrary expressions in a requires-clause. [ Example:
template<int N> requires N == sizeof new unsigned short
int f(); // error: parentheses required around == expression
— end example ]
在标准给出的上述示例中,编译器不可能知道 sizeof
部分是否应该被解析为表达式 new unsigned short
或 [=] 的 sizeof
15=]。在它周围加上括号,例如 requires (N == sizeof new unsigned short)
,可以解决问题。
以下代码是requires
子句的用法示例:
#include <type_traits>
template <typename T>
requires std::is_integral_v<T>
void take_integral(T value);
它接受一个计算为 bool
值(在本例中为 std::is_integral_v<T>
)的表达式,并按预期工作。
但是,当使用 !
运算符对此类表达式取反时,会导致编译错误:
#include <type_traits>
template <typename T>
requires !std::is_integral_v<T>
void take_integral(T value);
来自 GCC 的诊断:
<source>:4:12: error: expression must be enclosed in parentheses
4 | requires !std::is_integral_v<T>
| ^~~~~~~~~~~~~~~~~~~~~~
| ( )
Compiler returned: 1
来自 Clang 的诊断:
<source>:4:12: error: parentheses are required around this expression in a requires clause
requires !std::is_integral_v<T>
^~~~~~~~~~~~~~~~~~~~~~
( )
1 error generated.
Compiler returned: 1
这里为什么需要括号?
括号是必需的,因为它们避免了语言解析歧义。
并非每个表达式都允许在 requires
子句中。事实上,该标准给出了一个示例,说明如果允许所有表达式,将如何出现解析歧义:
[...] The expression in a requires-clause uses a restricted grammar to avoid ambiguities. Parentheses can be used to specify arbitrary expressions in a requires-clause. [ Example:
template<int N> requires N == sizeof new unsigned short int f(); // error: parentheses required around == expression
— end example ]
在标准给出的上述示例中,编译器不可能知道 sizeof
部分是否应该被解析为表达式 new unsigned short
或 [=] 的 sizeof
15=]。在它周围加上括号,例如 requires (N == sizeof new unsigned short)
,可以解决问题。