2011-05-23 8 views
10

Supongamos que tengo un objeto de algunas de las clases de contenedor stl obj. Puedo definir otro objeto del mismo tipo de esta manera:Comportamiento de decltype

decltype(obj) obj2; 

Pero no puedo declarar iterador para el contenedor de esta manera:

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

¿Por qué? ¿Estoy haciendo algo mal?

Respuesta

15

Su código está bien formado de acuerdo con el borrador final de C++ 0x (FDIS) . Este fue un cambio tardío que aún no ha sido implementado por el compilador de Visual Studio.

Mientras tanto, una solución es utilizar un typedef:

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

EDIT: El pelos y señales relevante es 5.1.1/8:

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

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

decltype-specifier: 
    decltype (expression) 

Y por amor de exhaustividad :

The original core issue

Proposal for wording

+0

Gracias @JohannesD.Si edita su respuesta agregando el número de párrafo del borrador final que dice esto, aceptaré su respuesta. –

+0

@Mihran - Aquí tienes :) – JohannesD

7

Es por la forma en que se analiza el lenguaje.

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

usted quiere que se convierta en

(decltype(obj)::iterator) it; 

Pero, en realidad, se convierte en

decltype(obj) (::iterator) it; 

tengo que admitir, que también se sorprendió al ver que este era el caso, como estoy seguro de que he hecho esto antes. Sin embargo, en este caso, es posible que utilices auto, o incluso decltype(obj.begin()), pero, además, se puede hace

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

Gracias por 'auto'. Pero el defraudamiento de tipos no es una buena idea en mi opinión. Estoy haciendo esto para evitar la extinción de tipos. –

+0

@Mihran Hovsepyan: ¿Por qué? Su código depende de un estándar 'typedef', apenas' typedef'-free. 'typedef' es difícilmente evitable en C++ tal como está. – Puppy

+0

mi definación de clase está en el encabezado, pero los métodos en cpp, por lo que cada vez durante la implementación de cpp debería abrir el encabezado y mirar qué es el tipo de un miembro. Pero como todo programador, estoy tratando de ser perezoso)) –

2

Sin embargo, otra solución hasta analizador VC++ 's se fija para reflejar el FDIS es utilizar el std::identity<> metafunción:

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

FWIW, 'std :: identity' se ha eliminado, por lo que es efectivamente dependiente de VC2010. (Aunque es lo suficientemente simple como para escribirlo) – GManNickG

+0

@GMan: Correcto, solo lo mencioné porque la pregunta del OP era específica de VC++ 2010. : -] – ildjarn