下面的代碼使用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