下面的代码使用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扩展?
下面的代码使用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扩展?
这很好。 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 *)是相同的类型。 - 注完]
获得链接?.321 –
@AaronHall“C++ 11”标准版在此处销售:http://webstore.ansi.org/RecordDetail.aspx?sku=INCITS%2FISO%2FIEC+14882-2012但您可以通过Google搜索“n3290.pdf”获得免费草稿(接近完全相同?)。所有草稿(但不包括)决赛都是免费的。 – Galik
如果我们在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
。这使我相信每个函数参数在每个后续参数之前是已知的。这意味着你应该能够使用它的类型。您无法使用它的值 - 因为值的评估顺序未指定 - 但名称应按从左到右的顺序引入。
他们肯定是在范围内,但这足够吗? – MSalters
@MSalters使用'decltype'我认为是。 – NathanOliver
是的,这是合法的。这基本上只是一个范围问题。从[basic.scope.block]:
函数参数名的电位范围(包括一个出现在λ-声明符)或在函数定义的函数本地预定义的变量的(8.4)从宣言的角度开始。
的arg1
范围从这里开始:
void func(int arg1, decltype(arg1) arg2)
------------------^
因此arg1
所在范围内的arg2
声明。我认为这就足够了。
禁止违约的规则arg2
至arg1
是分开的 - 对我而言,暗示arg1
在范围内,必须明确禁止。
我认为arg1'的'类型要复杂得多在你的实际代码?没有看规范或任何引用,但知道一些关于解析,我想这没关系,因为像C++这样的解析语言是非常重要的从左到右的事情。当编译器解析'arg2'的声明时,它必须已经解析了'arg1'的声明,所以它肯定知道'arg1'的类型。如果它真的被“允许”,我不知道,如果它的方向相反(使用'decltype(arg2)'作为'arg1')。 –
@JoachimPileborg当然,对于'arg1',实际的代码有更复杂的类型,否则我甚至会想到试着对它使用'decltype'。 – Ruslan
FWIW,MSVC++ 2013及其Intellisense(EDG)都可以接受。 – MSalters