2016-03-01 50 views
34

下面的代码使用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扩展?

+0

我认为arg1'的'类型要复杂得多在你的实际代码?没有看规范或任何引用,但知道一些关于解析,我想这没关系,因为像C++这样的解析语言是非常重要的从左到右的事情。当编译器解析'arg2'的声明时,它必须已经解析了'arg1'的声明,所以它肯定知道'arg1'的类型。如果它真的被“允许”,我不知道,如果它的方向相反(使用'decltype(arg2)'作为'arg1')。 –

+0

@JoachimPileborg当然,对于'arg1',实际的代码有更复杂的类型,否则我甚至会想到试着对它使用'decltype'。 – Ruslan

+0

FWIW,MSVC++ 2013及其Intellisense(EDG)都可以接受。 – MSalters

回答

20

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

首先,所述参数是在范围:

3.3.3块范围[ basic.scope。本地]

函数参数名的电位范围(包括一个出现在λ-声明符)或 在函数定义(8.4)的函数的本地预定义的变量开始在其申报点。

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

8.3.5功能[ dcl.fct ]

[注:这种转变呢不影响参数的类型。例如,int(*)(const int p,decltype(p)*)和int(*)(int,const int *)是相同的类型。 - 注完]

+0

获得链接?.321 –

+3

@AaronHall“C++ 11”标准版在此处销售:http://webstore.ansi.org/RecordDetail.aspx?sku=INCITS%2FISO%2FIEC+14882-2012但您可以通过Google搜索“n3290.pdf”获得免费草稿(接近完全相同?)。所有草稿(但不包括)决赛都是免费的。 – Galik

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 。这使我相信每个函数参数在每个后续参数之前是已知的。这意味着你应该能够使用它的类型。您无法使用它的值 - 因为值的评估顺序未指定 - 但名称应按从左到右的顺序引入。

+0

他们肯定是在范围内,但这足够吗? – MSalters

+0

@MSalters使用'decltype'我认为是。 – NathanOliver

10

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

函数参数名的电位范围(包括一个出现在λ-声明符)或在函数定义的函数本地预定义的变量的(8.4)从宣言的角度开始。

arg1范围从这里开始:

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

因此arg1所在范围内的arg2声明。我认为这就足够了。

禁止违约的规则arg2arg1是分开的 - 对我而言,暗示arg1在范围内,必须明确禁止。