gcc或clang对此行为是否正确?

gct*_*gct 38 c++ gcc clang language-lawyer c++11

我有一个小玩具程序:

static int value = 0;

int function(int &value=value) {
    return value;
}

int main() {
    function();
}
Run Code Online (Sandbox Code Playgroud)

使用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.
Run Code Online (Sandbox Code Playgroud)

KABOOM.谁是对的?

R S*_*ahu 32

我认为铿锵是正确的.来自basic.scope.pdecl:

名称的声明点紧跟在其完整的声明(子句[dcl.decl])之后和其初始化程序之前(如果有的话),除非如下所述.[例如:

int x = 12;{ int x = x; }
Run Code Online (Sandbox Code Playgroud)

这里第二个x用它自己的(不确定的)值初始化. - 结束例子]

另外,来自dcl.fct.default:

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

  • 这看起来像答案,惊讶的gcc错过了那一个. (3认同)
  • @VTT [这一个](https://timsong-cpp.github.io/cppwp/n3337/dcl.fct.default#9). (2认同)

Joh*_*han 18

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

在函数parameter-declaration-clause中查找用作默认参数(8.3.6)的名称或在构造函数(12.6.2)的mem-initializer表达式中使用时,函数参数名称是可见的,隐藏包含函数声明的块,类或命名空间范围中声明的实体的名称.

因此,铿锵是正确的.


Nat*_*ica 8

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

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

声明的定义是

声明的声明就在其完整的声明者之后和初始化者之前(如果有的话),除非如下所述.[例如:

unsigned char x = 12;
{ unsigned char x = x; }
Run Code Online (Sandbox Code Playgroud)

这里第二个x用它自己的(不确定的)值初始化. - 结束例子]

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