2011-05-23 14 views
10

Powiedzmy, że mam obiekt niektórych klas kontenera STL obj. Mogę określić inny obiekt tego samego typu w ten sposób:Zachowanie decltype

decltype(obj) obj2; 

Ale nie mogę zadeklarować iterator do pojemnika w ten sposób:

decltype(obj)::iterator it = obj.begin(); 

Dlaczego? czy robię coś źle?

Odpowiedz

15

Kod jest dobrze uformowane zgodnie z ostatecznym projektem C++ 0x (FDIS) . To była późna zmiana, której jeszcze nie zaimplementował kompilator Visual Studio.

W międzyczasie obejście jest użycie typedef:

typedef decltype(obj) obj_type; 
obj_type::iterator it = obj.begin(); 

EDIT: Odpowiedni rozdział i werset 5.1.1/8:

 
qualified-id: 
    [...] 
    nested-name-specifier templateoptunqualified-id 

nested-name-specifier: 
    [...] 
    decltype-specifier :: 

decltype-specifier: 
    decltype (expression) 

i dla zapewnienia kompletności za :

The original core issue

Proposal for wording

+0

Dziękuję @JohannesD.Jeśli edytujesz swoją odpowiedź dodając numer końcowy wersji roboczej, który mówi, że przyjmuję twoją odpowiedź. –

+0

@Mihran - Proszę bardzo :) – JohannesD

7

Dzieje się tak ze względu na sposób analizowania języka.

decltype(obj)::iterator it = obj.begin(); 

chcesz go stać

(decltype(obj)::iterator) it; 

Ale w rzeczywistości, staje

decltype(obj) (::iterator) it; 

Muszę przyznać, byłem też zaskoczony, aby zobaczyć, że to był przypadek, ponieważ jestem pewien, że już to zrobiłem. Jednak w tym przypadku, można po prostu użyć auto lub nawet decltype(obj.begin()), ale dodatkowo, ty może zrobić

typedef decltype(obj) objtype; 
objtype::iterator it; 
+0

Dziękujemy za 'auto'. Ale w moim przekonaniu typowanie nie jest dobrym pomysłem. Robię to, aby uniknąć typowania. –

+0

@Mihran Hovsepyan: Dlaczego? Twój kod jest zależny od standardowego 'typedef' - prawie wcale nie jest" typedef ". "typedef" trudno jest uniknąć w C++ w jego obecnym stanie. – Puppy

+0

Moja definicja klasy jest w nagłówku, ale metody w cpp, więc za każdym razem podczas wdrażania cpp powinienem otworzyć nagłówek i sprawdzić, jaki jest typ członka. Ale jak każdy programista staram się być leniwym)) –

2

Kolejny obejście aż parsera VC++ 's jest ustalony w celu odzwierciedlenia FDIS jest użycie std::identity<> metafunkcji:

std::identity<decltype(obj)>::type::iterator it = obj.begin(); 
+1

FWIW, 'std :: identity' został usunięty, więc jest to zależne od VC2010. (Jest to jednak dość proste, aby go napisać). – GManNickG

+0

@GMan: Tak, wspomniałem tylko, ponieważ pytanie OP było specyficzne dla VC++ 2010. : -] – ildjarn

Powiązane problemy