2016-11-09 49 views
9
enum class E { 
    One, 
    Two 
}; 

void foo(E value = decltype(value)::One) { 
} 

Może być skompilowany z Clang (3.9), ale nie można go skompilować z GCC 6.1: value was not declared in this scope.Używanie nazwy parametru w jego domyślnej wartości - czy jest legalne?

Jaki kompilator ma rację?

+0

Wygląda na to, że [this] (http://stackoverflow.com/questions/1880866/c-c-default-argument-set-as-a-previous-argument) jest odpowiedzią, ale nie jestem w 100% pewny. Pozostawiając go innym, aby zdecydować, czy należy go zamknąć jako dupę. – NathanOliver

+0

@NathanOliver To pytanie dotyczy dostępu do wartości parametru, co nie jest możliwe z dobrego powodu (kolejność oceny), ale spodziewam się, że jego nazwa i typ będą podlegać innym regułom, ponieważ ta przyczyna nie ma na nie wpływu. – Quentin

+0

@Quentin Dlatego nie głosowałem, aby zamknąć. Cytat ze standardu ma * W związku z tym parametry funkcji nie będą używane w domyślnych wyrażeniach argumentów, nawet jeśli nie są one oceniane. * I nie jestem pewien, czy ma to zastosowanie tutaj, czy nie. – NathanOliver

Odpowiedz

8

Według [basic.scope.pdecl]/1:

Punktem deklaracji o podanie nazwy jest natychmiast po jej całkowitym declarator (punkt 8) i przed jego initializer (jeśli występują), z wyjątkiem opisane poniżej.

Tak więc parametr jest zadeklarowany w tym miejscu. Jak o użyciu go w decltype? Sformułowanie było nieaktualne i nieumyślnie je odrzuciło. Zobacz core issue 2082:

Według 8.3.6 [dcl.fct.default] pkt 9,

domyślny argumentem jest oceniana za każdym razem gdy funkcja jest wywoływana z żaden argument dla odpowiedniego parametru. 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. Ta zakazuje wykorzystania parametrów w unevaluated argumentów, np,

void foo(int a = decltype(a){}); 

Sformułowanie poprzedza koncepcję z „unevaluated argumentów” (wyrażenie „nie ocenia” odnosi się do połączeń do funkcji, gdzie rzeczywiste argumentów jest dostarczany, a zatem domyślny argument nie jest używany, a nie niezaktualizowany operand) i nie powinien mieć zastosowania w takich przypadkach.

Więc quoted paragraph został zmieniony, aby przeczytać

parametr nie powinien pojawić się jako potencjalnie oceniano ekspresję w domyślnym argumentem.

Ponieważ operandy decltype są nieocenione, teraz jest to w porządku, a GCC jest błędne.

+1

Zostało to wprowadzone tylko w wersji roboczej, ale nie w C++ 14. http://wg21.cmeerw.net/cwg/issue2082 – vladon

+0

@vladon Tak, znalazłem to także po komentarzu Krzaqa. – Columbo

+0

Czy GCC naprawdę jest w błędzie, czy po prostu trzeba zaktualizować kompilację w C++ 17/1z? Wygląda na to, że w C++ 14 było to zabronione, więc naprawdę nie możesz za to winić GCC. – NathanOliver