2012-01-14 14 views
10

NOTA: Esta pregunta se realizó originalmente en el año 2012. Antes de que el especificador decltype fuera implementado por completo por cualquier compilador importante. No debería mirar este código a menos que solo tenga acceso a C++ 03. Todos los principales compiladores que cumplen con C++ 11 ahora son compatibles con decltype.Obteniendo el tipo de miembro

¿Hay alguna manera fácil de recuperar el tipo de miembro?
En C++ 03

struct Person 
{ 
    std::string name; 
    int   age; 
    double  salary; 
}; 

int main() 
{ 
    std::vector<Person>  people; // get a vector of people. 

    std::vector<GET_TYPE_OF(Person::age)> ages; 

    ages.push_back(people[0].age); 
    ages.push_back(people[10].age); 
    ages.push_back(people[13].age); 

} 

De hecho, estoy haciendo esto (es decir, ser un poco perezoso):

#define BuildType(className, member, type)         \ 
     struct className ## member: TypeBase<className, type>    \ 
     {                 \ 
      className ## member()           \ 
       : TypeBase<className, type>(#member, &className::member) \ 
      {}                \ 
     } 

BuildType(Person, name,  std::string); 
BuildType(Person, age,  int); 
BuildType(Person, salary, double); 
typedef boost::mpl::vector<Personname, Personage, Personsalary> FunckyMTPMap; 

Pero en lugar de tener que forzar al usuario a especificar el tipo del miembro quiero al compilador para generarlo pragmáticamente.

#define BuildType(className, member)             \ 
struct className ## member: TypeBase<className, TYPE_OF(className ## member)>   \ 
{                      \ 
    className ## member()                \ 
     : TypeBase<className, TYPE_OF(className ## member)>(#member, &className::member)\ 
    {}                     \ 
} 
BuildType(Person, name); 
BuildType(Person, age); 
BuildType(Person, salary); 
typedef boost::mpl::vector<Personname, Personage, Personsalary> FunckyMTPMap; 
+0

No creo que C++ le permita siquiera hablar de 'Persona :: edad' sin tener una instancia de' Persona' –

+0

@SethCarnegie: Si eso es cierto (y creo que puede ser), es algo molesto. ¿Cómo se descubre el tamaño de 'Persona :: edad'? –

+0

¿qué tal crear algo así como 'typedef int Person :: age_t;'? – greatwolf

Respuesta

9
template <class T, class M> M get_member_type(M T:: *); 

#define GET_TYPE_OF(mem) decltype(get_member_type(mem)) 

es la forma en C++ 11. Requiere que use &Person::age en lugar de Person::age, aunque puede ajustar fácilmente la macro para hacer el símbolo comercial implícito.

+0

Sweet, esto funciona (al menos para mí) –

5

En C++ 2003 que no se puede hacer directamente, sino que puede delegar en una plantilla de función que deduce el tipo:

template <typename T, typename S> 
void deduce_member_type(T S::* member) { 
    ... 
} 

int main() { 
    deduce_member_type(&Person::age); 
} 
1

Dado que en sus ejemplos se utiliza impulso que haría uso de TypeOf de impulso .

http://www.boost.org/doc/libs/1_35_0/doc/html/typeof.html

que funciona de manera muy similar a decltype de C++ 11.

http://en.wikipedia.org/wiki/C%2B%2B11#Type_inference en su caso:

std::vector<BOOST_TYPEOF(Person::age) > ages; 

puede comparar los tipos decltype o BOOST_TYPEOF le da con typeinfo

#include <typeinfo> 
cout << typeid(obj).name() << endl; 

que necesita para hacer un vector de la gente adecuada con una longitud> 14 para el ejemplo para trabajar.

gcc tiene typeof o typeof haciendo lo mismo.

Como nota al margen. Para el ejemplo que le dio, podría definir los tipos en la estructura si ninguno de los anteriores es relevante para usted.

struct Person 
{ 
    typedef int agetype; 
    std::string name; 
    agetype   age; 
    int   salary; 
}; 

a continuación, utilizar std :: vector :: < persona agetype> edades;

Cuestiones relacionadas