问题
NOTE: This question was originally asked way back in 2012. Before the decltype
specifier was fully implemented by any major compilers. You should not be looking at this code unless you only have access to C++03. All major C++11 compliant compilers now support decltype
.
Is there an easy way to retrieve the type of a member?
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);
}
I am actually doing this (ie being slightly lazy):
#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;
But rather than have to force the user to specify the type of the member I want to the compiler to generate it pragmatically.
#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;
回答1:
template <class T, class M> M get_member_type(M T:: *);
#define GET_TYPE_OF(mem) decltype(get_member_type(mem))
Is the C++11 way. It requires you to use &Person::age
instead of Person::age
, although you could easily adjust the macro to make the ampersand implicit.
回答2:
In C++2003 it can't be done directly but you can delegate to a function template which deduces the type:
template <typename T, typename S>
void deduce_member_type(T S::* member) {
...
}
int main() {
deduce_member_type(&Person::age);
}
回答3:
Since in your examples you use boost I'd use TYPEOF from boost.
http://www.boost.org/doc/libs/1_35_0/doc/html/typeof.html
it works very similarly to decltype of C++11.
http://en.wikipedia.org/wiki/C%2B%2B11#Type_inference in your case:
std::vector<BOOST_TYPEOF(Person::age) > ages;
you can compare the types decltype or BOOST_TYPEOF gives you with typeinfo
#include <typeinfo>
cout << typeid(obj).name() << endl;
you need to make a proper people vector with length >14 for the example to work.
gcc has typeof or typeof doing the same thing.
As a side note. For the example you gave you could just define the types in the struct instead if none of the above is relevant for you.
struct Person
{
typedef int agetype;
std::string name;
agetype age;
int salary;
};
then use std::vector< Person::agetype > ages;
来源:https://stackoverflow.com/questions/8866194/getting-the-type-of-a-member