C++20 概念的一个角落是在某些情况下您必须编写requires requires. 例如,来自[expr.prim.req]/3的这个例子:
requires requires
requires-expression 也可以在requires -clause ([temp]) 中使用,作为在模板参数上编写临时约束的一种方式,如下所示: template<typename T> requires requires (T x) { x + x; } T add(T a, T b) { return a + b; } 第一个 requires 引入了 requires-clause ,第二个引入了 requires-expression 。
requires-expression 也可以在requires -clause ([temp]) 中使用,作为在模板参数上编写临时约束的一种方式,如下所示:
template<typename T> requires requires (T x) { x + x; } T add(T a, T b) { return a + b; }
第一个 requires 引入了 requires-clause ,第二个引入了 requires-expression 。
需要第二个requires关键字背后的技术原因是什么?为什么我们不能只允许写作:
requires
template<typename T> requires (T x) { x + x; } T add(T a, T b) { return a + b; }
(注:请不要回答那个语法requires吧)
这是因为语法需要它。确实如此。
约束requires不必使用表达式。它可以使用任何或多或少的任意布尔常量表达式。因此,必须是一个合法的约束。 __requires``requires (foo)``requires
requires``requires (foo)``requires
requires 表达式 (测试某些事物是否遵循某些约束的事物)是一个独特的构造;它只是由相同的关键字引入的。requires (foo f)将是有效requires表达式的开始。
requires (foo f)
您想要的是,如果您requires在接受约束的地方使用,您应该能够从requires子句中制作“约束+表达式”。
所以这里的问题是:如果你放入requires (foo)一个适合需求约束的地方......解析器必须走多远才能意识到这是一个需求 约束 而不是你想要的约束+表达式成为?
requires (foo)
考虑一下:
void bar() requires (foo) { //stuff }
iffoo是一个类型,then(foo)是一个 requires 表达式的参数列表,其中的所有内容{}都不是函数的主体,而是该requires表达式的主体。否则,foo是requires子句中的表达式。
foo
(foo)
{}
好吧,你可以说编译器应该首先弄清楚什么foo是第一个。但是 C 真的 不喜欢它,因为解析标记序列的基本行为需要编译器在理解标记之前弄清楚这些标识符的含义。是的,C 是上下文相关的,所以这确实发生了。但委员会倾向于尽可能避免这种情况。
所以是的,这是语法。