2016-03-01 12 views
34

Poniższy kod kompiluje czysto GCC:Czy można użyć poprzedniego parametru funkcji do zadeklarowania nowego?

void func(int arg1, decltype(arg1) arg2) 
{ 
    (void)arg2; 
} 
int main(){} 

użyłem tego polecenia do kompilacji:

g++ -std=c++14 test.cpp -o test -pedantic-errors -Wall -Wextra 

Ale takie użycie parametru w środku deklaracji funkcji wydaje się dziwne. Czy rzeczywiście jest prawidłowe w standardowym C++, czy jest to rozszerzenie GCC?

+0

Zakładam, że typ 'arg1' jest dużo bardziej skomplikowana w rzeczywistym kodzie? I bez patrzenia na specyfikację lub jakiekolwiek referencje, ale wiedząc trochę o analizie składniowej, zgaduję, że to jest w porządku, ponieważ parsowanie języków takich jak C++ jest bardzo sprawą od góry do dołu od lewej do prawej. Gdy kompilator analizuje deklarację dla "arg2", musi już przeanalizować deklarację "arg1", więc na pewno zna typ "arg1". Jeśli jest to naprawdę "dozwolone", nie wiem, ani czy działa w przeciwnym kierunku (używając 'decltype (arg2)' dla 'arg1'). –

+0

@JoachimPileborg oczywiście, rzeczywisty kod ma znacznie bardziej złożony typ dla 'arg1', w przeciwnym razie nawet pomyślałem o użyciu' decltype' na nim. – Ruslan

+0

FWIW, MSVC++ 2013 i jego IntelliSense (EDG) zarówno go akceptują. – MSalters

Odpowiedz

20

To jest w porządku. ISO C++11 Standard podaje nawet Twoją sytuację jako przykład.

Pierwszy parametr jest w zakresie:

3.3.3 bloku zakres [ basic.scope.miejscowy ]

potencjalny zakres nazwą parametrów funkcji (łącznie z jednym znajdującym się w lambda-declarator) lub funkcję lokalnego predefiniowany zmienna w definicji funkcji (8.4) rozpoczyna się jego punkt deklaracji.

Przykład można znaleźć tutaj:

8.3.5 Funkcje [ dcl.fct ]

[ Uwaga: Ta przemiana robi nie wpływa na typy parametrów. Na przykład int (*) (const int p, decltype (p) *) i int (*) (int, const int *) są identycznymi typami. - koniec uwaga ]

+0

Masz link? .321 –

+3

@AaronHall Standaard 'C++ 11' jest sprzedawany tutaj: http://webstore.ansi.org/RecordDetail.aspx?sku=INCITS%2FISO%2FIEC+14882-2012, ale możesz uzyskać darmową wersję roboczą (prawie identyczną?) przez szukanie w Google dla "n3290.pdf". Wszystkie projekty do (ale nie włącznie) finału są bezpłatne. – Galik

6

Jeśli spojrzymy w N3979 [dcl.fct.default] mamy

argumenty domyślne są oceniane przy każdym wywołaniu funkcji. Kolejność oceny argumentów funkcji jest nieokreślona. W związku z tym parametry funkcji nie będą używane w domyślnym argumencie, nawet jeśli nie zostaną ocenione. Parametry funkcji zadeklarowanej przed domyślnym argumentem są w zakresie i mogą ukrywać przestrzeń nazw i nazwy członków klasy. [Przykład:

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 

[...]

Nacisk kopalnia

Więc na przykład a wiadomo, kiedy mamy do b i ukrywa a z zakresu wywołującego . To prowadzi mnie do przekonania, że ​​każdy parametr funkcji jest znany przed każdym kolejnym parametrem. Oznacza to, że powinieneś być w stanie używać jego typu. Nie można użyć jego wartości - ponieważ kolejność oceny wartości jest nieokreślona - ale nazwy należy wprowadzać w kolejności od lewej do prawej.

+0

Są zdecydowanie w zasięgu, ale czy to wystarczy? – MSalters

+0

@MSalters, aby używać ich z 'decltype' Myślę, że tak. – NathanOliver

10

Tak, jest to zgodne z prawem. Zasadniczo to tylko kwestia zakresu. W [basic.scope.block]

potencjalny zakres nazwa funkcji parametrów (w tym jeden występujący w lambda declarator) lub przez funkcję lokalnego zdefiniowanej zmiennej w definicji funkcji (8,4) rozpoczyna się w momencie złożenia deklaracji.

Zakres arg1 zaczyna się tutaj:

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

Stąd arg1 w zakres deklaracji arg2. Myślę, że to wystarczające.

Reguła odrzucania domyślnej arg2 do arg1 jest osobna - co do mnie sugeruje, że arg1 był w zakresie i musiał być wyraźnie zabroniony.

Powiązane problemy