2016-03-01 68 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在範圍內,必須明確禁止。