【问题标题】:Is it legal to use previous function parameter to declare new one?使用以前的函数参数声明新的函数参数是否合法?
【发布时间】:2016-06-13 23:02:45
【问题描述】:

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

【问题讨论】:

  • 我假设arg1 的类型在您的实际代码中要复杂得多?在不查看规范或任何参考资料的情况下,但对解析有所了解,我想这没关系,因为像 C++ 这样的解析语言在很大程度上是从上到下从左到右的事情。当编译器解析arg2 的声明时,它肯定已经解析了arg1 的声明,所以它肯定知道arg1 的类型。如果它真的被“允许”我不知道,它是否会在相反的方向工作(使用decltype(arg2) 代表arg1)。
  • @JoachimPileborg 当然,实际代码中arg1 的类型要复杂得多,否则我什至会考虑尝试在其上使用decltype。
  • FWIW、MSVC++2013 及其 Intellisense (EDG) 也都接受它。
  • 匹配参数参数的首选方法是通过模板参数(尽管这不是问题所要问的),但我认为您的提议是有效的。
  • @callyalater 但它不是函数模板。 OP 想要 arg1 的特定类型,以及 arg2 的相同类型(只是该类型显然是拼写的 PITA)

标签: c++ function gcc language-lawyer


【解决方案1】:

这很好。 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*) 是相同的类型。 ——尾注]

【讨论】:

  • @AaronHall C++11 标准在这里出售:webstore.ansi.org/… 但您可以通过谷歌搜索“n3290.pdf”获得免费草稿(几乎相同?)。直到(但不包括)决赛的所有草稿都是免费的。
【解决方案2】:

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

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

arg1 的范围从这里开始:

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

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

禁止默认 arg2 到 arg1 的规则是独立的——对我来说,这表明 arg1 在范围内,必须明确禁止。

【讨论】:

    【解决方案3】:

    如果我们查看 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
    

    [...]

    强调我的

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

    【讨论】:

    • 它们肯定在范围内,但这是否足够?
    • @MSalters 将它们与decltype 一起使用我想是的。
    猜你喜欢
    • 2018-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多