使用以前的函数参数来声明新函数是否合法?

时间:2016-03-01 13:37:47

标签: c++ function gcc language-lawyer

以下代码与GCC完全编译:

void func(int arg1, decltype(arg1) arg2)
{
    (void)arg2;
}
int main(){}

我用这个命令编译:

g++ -std=c++14 test.cpp -o test -pedantic-errors -Wall -Wextra

但是在函数声明中间使用参数似乎很奇怪。它在标准C ++中实际有效,还是GCC扩展?

3 个答案:

答案 0 :(得分:22)

这很好。 ISO C++11 Standard甚至以您的情况为例。

首先参数在范围内:

3.3.3 阻止范围 [ basic.scope.local ]

  

2 函数参数名称的潜在范围(包括一个出现在lambda声明符中)或者   函数定义(8.4)中的函数本地预定义变量从其声明点开始。

可以在这里找到一个例子:

  

8.3.5 功能 [ dcl.fct ]

     

5 [ 注意:此转换不会影响参数的类型。例如,int(*)(const int p,decltype(p)*)和int(*)(int,const int *)是相同的类型。 - 结束说明]

答案 1 :(得分:11)

是的,这是合法的。这基本上只是一个范围问题。来自[basic.scope.block]:

  

函数参数名称(包括出现在 lambda-declarator 中的名称)或函数定义中的函数本地预定义变量(8.4)的潜在范围从其声明点开始。

arg1的范围从这里开始:

void func(int arg1, decltype(arg1) arg2)
------------------^

因此,arg1arg2声明的范围。我认为这已经足够了。

禁止违约arg2arg1的规则是分开的 - 对我来说这表明arg1在范围内并且必须明确禁止。

答案 2 :(得分:6)

如果我们查看N3979 [dcl.fct.default],我们有

  

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

int a;
int f(int a, int b = a);              // error: parameter a
                                      // used as default argument
typedef int I;
int g(float I, int b = I(2));         // error: parameter I found
int h(int a, int b = sizeof(a));      // error, parameter a used
                                      // in default argument
     

[...]

强调我的

因此,示例a在我们到达b时就已知,并且它会从调用范围隐藏a。这使我相信每个函数参数在每个后续参数之前都是已知的。这意味着您应该能够使用其类型。您无法使用其值 - 因为未指定值的评估顺序 - 但应按从左到右的顺序引入名称。