【问题标题】:Why are parentheses needed around negated expressions in a requires-clause?为什么在 requires 子句中的否定表达式周围需要括号?
【发布时间】:2020-07-09 16:12:20
【问题描述】:

以下代码是requires-clause 的使用示例:

#include <type_traits>

template <typename T>
  requires std::is_integral_v<T>
void take_integral(T value);

它接受一个评估为bool 值的表达式(在本例中为std::is_integral_v&lt;T&gt;),并按预期工作。 但是,当使用! 运算符对此类表达式求反时,会导致编译错误:

#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

为什么这里需要括号?

【问题讨论】:

标签: c++ templates c++20 c++-concepts


【解决方案1】:

括号是必需的,因为它们避免了语言解析的歧义。

requires-clause 中不允许所有表达式。事实上,该标准给出了一个例子,说明如果所有表达式都被允许,解析歧义是如何产生的:

[temp.pre]/9

[...] requires-clause 中的表达式使用受限语法来避免歧义。 括号可用于在 requires-clause 中指定任意表达式。 [ 例子:

template<int N> requires N == sizeof new unsigned short
int f();            // error: parentheses required around == expression

—结束示例]

在标准给出的上述示例中,编译器不可能知道sizeof 部分是否应该被解析为表达式new unsigned shortnew unsigned short intsizeof。用括号括起来,比如requires (N == sizeof new unsigned short),可以解决问题。

【讨论】:

  • “表达式周围的括号 [...] 改变了约束的评估方式。”不,它不会...除了括号使其开头有效或您使用括号影响运算符优先级的明显情况之外。
  • godbolt.org/z/Xai_8K 是一个简短的演示,证明了(A || B) “做析取”。
  • 绝对是does disjunction, demo
  • @Barry 我认为这更像是一个证明(A || B) 参与包含而不是执行析取,但它确实表明(A || B) 不是原子约束表达式。
  • @Casey 我认为这是他想要的“不做分离”。
猜你喜欢
  • 1970-01-01
  • 2015-11-01
  • 2013-04-07
  • 1970-01-01
  • 1970-01-01
  • 2022-06-12
  • 2021-12-21
  • 2017-09-13
  • 2014-12-23
相关资源
最近更新 更多