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

时间:2018-02-13 16:42:31

标签: c++ c++11 gcc clang language-lawyer

我有一个小玩具程序:

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.

KABOOM。谁是对的?

3 个答案:

答案 0 :(得分:32)

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

  

名称的声明点紧接在其完整的声明者(条款[dcl.decl])之后和初始化者之前(如果有的话),除非如下所述。 [例如:

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

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

此外,来自dcl.fct.default

  

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

答案 1 :(得分:18)

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

  

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

因此,铿锵是正确的。

答案 2 :(得分:8)

Clang在这里是正确的。首先,function's parameter scope定义为:

  

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

point of declaration定义为

  

名称的声明点在其完整的声明者之后和初始化者之前(如果有的话),除非如下所述。 [实施例:

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

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

因此value应该是您刚刚声明的value而不是全球空间中的const env