GCC 或 Clang 关于函数参数在其自己的默认参数中的范围内的名称是否正确?

Is GCC or Clang correct about the name of a function parameter being in scope in its own default argument?

本文关键字:参数 范围内 默认 是否 自己的 于函数 Clang 函数 GCC      更新时间:2023-10-16

我有一个小玩具程序:

static int value = 0;
int function(int &value=value) {
return value;
}
int main() {
function();
}

使用 g++ 7.2 编译:

g++ -std=c++11 -wall -wextra test.cc -o test

没关系。

使用 clang++-3.9 编译:

clang++-3.9 -std=c++11 -wall -wextra test.cc -o test

test.cc:3:25: error: default argument references parameter 'value'
int function(int &value=value) {
^~~~~
test.cc:8:5: error: no matching function for call to 'function'
function();
^~~~~~~~
test.cc:3:5: note: candidate function not viable: requires single argument 'value', but no arguments were provided
int function(int &value=value) {
^
2 errors generated.

卡布姆。 谁是对的?

我认为clang是正确的。从basic.scope.pdecl:

名称的声明点紧接在其完整声明符(子句 [dcl.decl])之后和初始值设定项(如果有)之前,除非下面另有说明。[ 示例:

int x = 12;{ int x = x; }

在这里,第二个 x 使用它自己的(不确定)值进行初始化。 — 结束示例 ]

另外,从dcl.fct.default:

每次调用函数时都会计算默认参数。未指定函数参数的计算顺序。因此,函数的参数不应在默认参数中使用,即使它们未被计算。在默认参数之前声明的函数的参数在作用域中,可以隐藏命名空间和类成员名称

由于 OP 将问题标记为 c++11,我检查了该版本的标准,并在 [basic.lookup.unqual] 子条款 11 中明确指出:

在查找用作默认参数 (8.3.6) 的名称期间 函数参数声明子句或用于表达式 构造函数 (12.6.2) 的 mem 初始值设定项,函数参数 名称可见,并隐藏在 包含函数声明的块、类或命名空间作用域。

因此,叮当是正确的。

Clang在这里是正确的。 首先,函数的参数范围定义为:

函数参数(包括出现在 lambda 声明符中的参数)或函数局部预定义变量 ([dcl.fct.def]) 具有函数参数范围。参数或函数局部预定义变量的潜在范围从其声明点开始。[...]

声明点定义为

名称的声明点紧接在其完整声明符之后和初始值设定项(如果有)之前,除非下面另有说明。[ 示例:

unsigned char x = 12;
{ unsigned char x = x; }

在这里,第二个x用它自己的(不确定的)值初始化。

所以value应该是你刚刚宣布的value,而不是来自全球空间的

那个