2016-07-14 59 views
16

Więc jestem zakłopotany, jak to działa. Biorąc pod uwagę:Nie powinien dekompresować kompilacji argumentu?

template <typename T> 
int foo(T t) { t.foo(); } 

Wydaje się, że tej rozmowy nie uda:

decltype(foo(int{ 13 })) fail = 42; 

cout << fail << endl; 

Zamiast it just prints:

To działa w ten sposób na wszystkich kompilatorów mam dostęp do. Czy to prawidłowe zachowanie? Proszę o wycenę ze standardu C++.

+0

'std :: type_info :: name()' nie gwarantuje niczego niezawodnego. Czy daje coś innego w innych przypadkach? – StoryTeller

+0

@StoryTeller Usunąłem 'typ_info' z pytania. Mam nadzieję, że pomoże to wyjaśnić problem. To jest pytanie o 'decltype' i co jest wymagane, po prostu próbowałem użyć' type_info', aby zademonstrować pytanie. –

+5

'decltype' nie potrzebuje pełnej definicji funkcji, aby poznać wynikowy typ. ([Zobacz] (http://ideone.com/eHSQ92)). Nie ma więc powodu, aby kompilować coś innego niż prototyp. Ale nie mam standardowego cytatu. – StoryTeller

Odpowiedz

17

W [dcl.spec]:

do wyrażenia E, typ oznaczona decltype (E) jest zdefiniowana jako następująco:

jeżeli e jest unparenthesized ID ekspresja nazewnictwa lwartością lub odniesienia wprowadzanego z listy identyfikacyjnej deklaracji dekompozycji , decltype (e) jest typem referencyjnym podanym w specyfikacji deklaracji dekompozycji ([dcl.decomp]);

w przeciwnym razie, jeśli e jest nieprostnym wyrażeniem id lub nieprywatnym dostępem do klasy ([expr.ref]), decltype (e) jest typem podmiotu nazwanego przez e. Jeśli nie ma takiego obiektu lub jeśli e nazywa zestaw przeciążonych funkcji, program jest źle sformułowany;

w przeciwnym razie, jeśli e jest wartością x, decltype (e) to T & &, gdzie T jest typem e;

w przeciwnym razie, jeśli e jest lwartością, decltype (e) to T &, gdzie T jest typem e;

inaczej, decltype (e) jest typem e.

Operand specyfikatora decltype jest operatorem nieuzgodnionym (klauzula [wyrażenie]).

(Kopalnia nacisk)

Więc foo(int{ 13 }) nigdy nie jest oceniana.

+0

Doskonała odpowiedź, dzięki. Bałem się, że zaakceptuję [Jespera Juhla ", ponieważ powiedziałem" odpowiedź "(http://stackoverflow.com/a/38373961/2642059). –

+0

Zastanawiam się, czy to naprawdę oznacza, że ​​kompilacja musi odnieść sukces. Na przykład. w "1? 0: foo (int {13}) 'wywołanie nigdy nie jest oceniane, ale nie oczekiwałbym, że to się skompiluje. (Prawdopodobnie istnieją pewne szczegółowe zasady dotyczące tego, co dokładnie robi się w sprawdzaniu typu nieocenionych operandów ...?) – chi

+4

Jeśli zmienisz definicję powyższego szablonu funkcji na "szablon auto foo (T t) {t.foo(); } ', tworzenie wystąpienia szablonu wydaje się jednak mieć miejsce - co ma dla mnie sens, ponieważ bez dedukcji typu return nie ma możliwości, aby' decltype' dał jakąkolwiek wartość. To oczywiście kończy się błędem czasu kompilacji. Gdzie w powyższej klauzuli znajduje się to zachowanie? Czy czegoś brakuje? – thokra

5

Wyrażenia w decltype są zdefiniowane przez standard, aby nie podlegały ocenie, są analizowane tylko po to, aby uzyskać typ wyrażenia.

+5

Obowiązkowe pytanie dotyczące odniesienia do głównego dokumentu wszechświata. –

+6

To jedna krótka odpowiedź. Zamierzam zrobić komentarz na ten temat, który jest dłuższy niż sama odpowiedź: już ustaliłem, że kompilatory mam dostęp do wsparcia twojego oświadczenia. Pytanie brzmi: "Czy to prawidłowe zachowanie?" Aby ustalić, że będziesz potrzebować czegoś więcej niż zdobytej wiedzy. –

+0

@ Jonaton Widzicie, jaki jest pożytek z Ciebie? Mówi się, że kompilatory są poprawne, dlaczego potrzebujesz odwołania do specyfikacji? Czy zweryfikujesz swoją odpowiedź na podstawie tekstu spec? Na ile jesteś pewien, że nie dajesz się zwieść tej odpowiedzi, by uwierzyć, że specyfik mówi, niezależnie od tego, co mówi spec? –