Vraag Het type van een lid krijgen


NOTITIE: Deze vraag werd oorspronkelijk al in 2012 gesteld. Voor de decltype specifier werd volledig geïmplementeerd door alle belangrijke compilers. Je zou niet naar deze code moeten kijken, tenzij je alleen toegang hebt tot C ++ 03. Alle belangrijke C ++ 11 compilers ondersteunen dit nu decltype.

Is er een eenvoudige manier om het type van een lid op te halen?
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);

}

Ik doe dit eigenlijk (dwz enigszins lui zijn):

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

Maar in plaats van de gebruiker te dwingen om het type van het lid dat ik wil aan de compiler te specificeren om het pragmatisch te genereren.

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

10
2018-01-14 23:18


oorsprong


antwoorden:


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

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

Is de weg C ++ 11. Het vereist dat je gebruikt &Person::age in plaats van Person::age, hoewel je de macro eenvoudig kunt aanpassen om de ampersand impliciet te maken.


12
2018-01-14 23:21



In C ++ 2003 kan dit niet direct worden gedaan, maar u kunt delegeren naar een functiesjabloon die het type afleidt:

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

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

5
2018-01-14 23:34



Omdat je in je voorbeelden boost gebruikt zou ik TYPEOF van boost gebruiken.

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

het werkt erg op dezelfde manier als decltype van C ++ 11.

http://en.wikipedia.org/wiki/C%2B%2B11#Type_inference in jouw geval:

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

je kunt de typen decltype vergelijken of BOOST_TYPEOF geeft je met typeinfo

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

je moet een goede mensenvector maken met een lengte van> 14 om het voorbeeld te laten werken.

gcc heeft typeof of soort van hetzelfde doen.

Als een kanttekening. Voor het voorbeeld dat u gaf, kon u alleen de typen in de struct definiëren, als geen van de bovenstaande voor u relevant is.

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

gebruik dan     std :: vector <Person :: agetype> ages;


1
2018-01-14 23:42