需要带有 void 类型局部参数的表达式

问题描述 投票:0回答:1

requires-表达式可以使用参数列表引入本地参数。如果这些参数中的任何一个具有

void
类型,则 require 表达式是否会产生
false
还是会出现硬编译错误?

考虑示例#1:

template<typename T>
concept C = requires(T t, void v) {
    t;
};

static_assert(!C<int>);

Clang 和 MSVC 都接受,但 GCC 抱怨

错误:在参数声明中无效使用类型“void”

在线演示:https://gcc.godbolt.org/z/voMajE4K3

更简短的示例#2:

static_assert( requires(int t, void) {t;} );

再次被 Clang 接受,其中

requires
产生
true
。 GCC 发出同样的错误。 MSVC 现在打印:

错误 C2860:“void”不能用作除“(void)”之外的函数参数

在线演示:https://gcc.godbolt.org/z/eYbM49d7E

上面两个例子中哪个编译器是正确的?

c++ language-lawyer c++20 void requires-expression
1个回答
0
投票

所有编译器都是正确的。 requires-expression 中的无效参数类型会使 requires-expression 格式错误(不仅仅是 false),并且 [temp.res.general]/6.4 然后适用:

程序格式错误,无需诊断,如果

  • [...]
  • 程序中的任何
  • 约束表达式,无论引入或以其他方式,都具有(以其正常形式)原子约束A,其中A的满足检查可能是格式良好的,并且A的满足检查不成立执行,或
  • [...]
C

的定义有requires-expression作为它的constraint-expression,前者是一个原子约束,所以它的正常形式就是它本身。当确定是否满足约束时,由于代入该原子约束总是会产生无效表达式,因此会触发上述规则,程序为 IFNDR。 有些人希望

requires-expression

中的参数类型无效,以使 requires-expression 为 false,而不是格式错误 (CWG2565)。如果要进行这种更改,您的示例可能仍然是 IFNDR; [expr.prim.req.general]/5,当前为

如果将模板参数替换为
需求

总是会导致替换失败,则该程序是格式错误的;无需诊断。

可能会进行修改,以便它也适用于
参数声明子句

© www.soinside.com 2019 - 2024. All rights reserved.