2012-01-14 26 views
10

NOTA: questa domanda è stata originariamente richiesta nel lontano 2012. Prima che lo specificatore decltype fosse completamente implementato da qualsiasi compilatore principale. Non dovresti guardare questo codice a meno che tu non abbia solo accesso a C++ 03. Tutti i principali compilatori compatibili con C++ 11 ora supportano decltype.Ottenere il tipo di membro

C'è un modo semplice per recuperare il tipo di un membro?
In 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); 

} 

Io sto facendo questo (cioè di essere un po 'pigro):

#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; 

Ma piuttosto che dover costringere l'utente a specificare il tipo di elemento che voglio al compilatore per generarlo pragmaticamente.

#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

Non penso che il C++ ti permetta di parlare di 'Person :: age' senza avere un'istanza di' Person' –

+0

@SethCarnegie: Se ciò è vero (e penso che possa essere), è alquanto fastidioso. Come si scopre la dimensione di 'Person :: age'? –

+0

come creare qualcosa come "typedef int Person :: age_t;"? – greatwolf

risposta

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

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

è il modo C++ 11. È necessario utilizzare &Person::age anziché Person::age, sebbene sia possibile regolare facilmente la macro per rendere implicita la e commerciale.

+0

Dolce, questo funziona (almeno per me) –

5

In C++ 2003 non può essere fatto direttamente, ma si può delegare ad un modello di funzione che deduce il tipo:

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

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

Poiché nei tuoi esempi si utilizza spinta userei TypeOf dalla spinta .

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

funziona in modo molto simile a decltype di C++ 11.

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

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

è possibile confrontare i tipi decltype o BOOST_TYPEOF ti dà con typeinfo

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

è necessario effettuare una corretta le persone vettore con lunghezza> 14 per il esempio per lavorare.

gcc ha typeof o typeof fare la stessa cosa.

Come nota a margine. Per l'esempio che hai dato potresti semplicemente definire i tipi nella struct se invece nessuno dei precedenti è rilevante per te.

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

quindi utilizzare std :: vector < persona :: agetype> età;

Problemi correlati