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

35
以下代码在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的扩展功能?


@JoachimPileborg 当然,实际上的代码arg1类型更加复杂,否则我甚至不会考虑尝试使用decltype - Ruslan
顺带一提,MSVC++2013及其Intellisense (EDG)也都能够接受它。 - MSalters
1
匹配参数的首选方法是通过模板参数(虽然这不是问题所询问的),但我认为您提出的方法是有效的。 - callyalater
1
@callyalater 但这不是一个函数模板。OP想要一个特定类型的 arg1,并且对于 arg2 也是同样的类型(只是这个类型很难拼写)。 - Barry
@Barry 我知道。这就是为什么我在我的评论中指明了(“这不是问题所要求的”)。我提供了一个额外的解决问题的方法。 - callyalater
显示剩余2条评论
3个回答

22

这是正常的。甚至ISO C++11标准将您的情况作为一个示例。

首先,参数在作用域内:

3.3.3 块作用域 [ basic.scope.local ]

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

可以在此处找到一个示例:

8.3.5 函数 [ dcl.fct ]

5 [ 注意:这种转换不会影响参数的类型。例如,int(*)(const int p, decltype(p)*) 和 int(*)(int, const int*) 是相同的类型。 — end note ]


3
@AaronHall C++11标准在这里出售:http://webstore.ansi.org/RecordDetail.aspx?sku=INCITS%2FISO%2FIEC+14882-2012,但您可以通过搜索“n3290.pdf”获得一个免费的草案(几乎相同?)。 所有的草案直到(但不包括)最终版本都是免费的。 - Galik

11

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

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

arg1的作用域从此处开始:

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

因此,arg1 对于声明 arg2 是在作用域内的。我认为这就足够了。

禁止把 arg2 默认值设为 arg1 的规则是单独的 - 这对我来说意味着 arg1 是在作用域内且必须显式地被禁止。


6

如果我们查看N3979 [dcl.fct.default],我们会发现:

Default arguments are evaluated each time the function is called. The order of evaluation of function arguments is unspecified. Consequently, parameters of a function shall not be used in a default argument, even if they are not evaluated. Parameters of a function declared before a default argument are in scope and can hide namespace and class member names. [ Example:

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

[...]

强调是我的

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


它们肯定在范围内,但这是否足够呢? - MSalters
@MSalters 我认为可以使用decltype来使用它们。 - NathanOliver

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接