Получение типа члена - PullRequest
       27

Получение типа члена

12 голосов
/ 15 января 2012

ПРИМЕЧАНИЕ : Этот вопрос первоначально задавался еще в 2012 году. До того, как спецификатор decltype был полностью реализован любыми крупными компиляторами. Вы не должны смотреть на этот код, если у вас есть только доступ к C ++ 03. Все основные компиляторы, совместимые с C ++ 11, теперь поддерживают decltype.

Есть ли простой способ получить тип члена?
В С ++ 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);

}

На самом деле я делаю это (то есть немного ленив):

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

Но вместо того, чтобы заставлять пользователя указывать тип элемента, который я хочу, чтобы компилятор генерировал его прагматично.

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

Ответы [ 3 ]

14 голосов
/ 15 января 2012
template <class T, class M> M get_member_type(M T:: *);

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

Является ли C ++ 11 способом. Требуется, чтобы вы использовали &Person::age вместо Person::age, хотя вы могли бы легко настроить макрос, чтобы сделать амперсанд неявным.

5 голосов
/ 15 января 2012

В C ++ 2003 это нельзя сделать напрямую, но вы можете делегировать шаблон функции, который выводит тип:

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

int main() {
    deduce_member_type(&Person::age);
}
1 голос
/ 15 января 2012

Так как в ваших примерах вы используете boost, я бы использовал TYPEOF из boost.

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

работает очень похоже на decltype C ++ 11.

http://en.wikipedia.org/wiki/C%2B%2B11#Type_inference в вашем случае:

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

вы можете сравнить типы decltype или BOOST_TYPEOF, которые вы можете получить, с typeinfo

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

вам нужно создать правильный вектор людей длиной> 14, чтобы пример работал.

gcc имеет typeof или typeof делает то же самое.

Как примечание. Для приведенного вами примера вы можете просто определить типы в структуре, если ничего из вышеперечисленного не подходит для вас.

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

затем используйте std :: vector ages;

...