2

Is it possible to list member variable names and their type programmatically? e.g:

class MyClass
{
public:
    MyClass();
    ~MyClass();
private:
    uint16_t    bob;
    uint8_t     dave;
    uint8_t     mick;
    int8_t     bazzer;    
};

I need to find (in code) what the variable names are and how big they are i.e. bob is a uint16_t. I understand that there is something in Java called 'reflection' and this seems to do what I want but I'm after something in straight up C++.

roalz
  • 2,581
  • 3
  • 24
  • 41
Chris
  • 327
  • 3
  • 13
  • 2
    maybe this can help you [link](http://stackoverflow.com/questions/41453/how-can-i-add-reflection-to-a-c-application) – BeerBaron Feb 06 '14 at 16:57

1 Answers1

3

No, there is no reflection in C++, what you want is not possible.

You can however make every class conforming to an interface defined you. Although this requires you to provide the information manually:

struct Foo
{
    uint16_t bar;
    char bar2;

    //maybe you want to return a typeid hash here instead of a string
    static std::map<std::string, std::string> GetMembers()
    {
        return {("bar", "uint16_t"), ("bar2", "char")}; 
    }
}

A code-generator could do this job for you by generating an AST and than inserting the above piece of code.

For a more advanced approach I would return a std::vector<MemberInfo> with MemberInfo being a class holding all relevant informations.

Such an approach could look like:

struct MemberInfo
{
    std::string m_name;
    size_t m_size;
};

template<typename T>
struct Reflection;

template<>
struct Reflection<Foo>
{  
   static std::vector<MemberInfo> GetMembers()
   {
       return {{"bar", sizeof(decltype(Foo::bar))}, {"bar2", sizeof(decltype(Foo::bar2))}}
   }
};

template<typename T>
void PrintMembers()
{
    for (auto& member : Reflection<T>::GetMembers())
    {
        std::cout << "name: " << member.m_name << " size: " << member.m_size << std::endl;
    }
}
Sebastian Hoffmann
  • 10,024
  • 5
  • 43
  • 74
  • 1
    Does this mean that it's definitely not possible or that it doesn't have reflection? – Chris Feb 06 '14 at 16:56
  • @Chris: It means that C++ doesn't have reflection and what you want is definitely not possible. – rici Feb 06 '14 at 16:59
  • @Chris May be C++ CLR extensions support such feature. Simple RTTI doesn't, using a straightforward way. – πάντα ῥεῖ Feb 06 '14 at 16:59
  • @rici There are mechanisms (e.g. like the ones used with google-protobuf), that come near to reflection. But in general there's no such feature, yes! – πάντα ῥεῖ Feb 06 '14 at 17:01
  • @πάνταῥεῖ: google-protobuf uses a separate protocol compiler which creates protobuf descriptors. Obviously, you could create a static structure for each of your structs which adds introspection. You could probably even write an add-on to clang which produces such things. But none of those are part of C++. – rici Feb 06 '14 at 17:05
  • @rici _But none of those are part of C++._ Of course they aren't and I mentioned that. I agreed what you're saying ... – πάντα ῥεῖ Feb 06 '14 at 17:08
  • 1
    @Chris But `typeinfo`/`std::typeid` isn't sufficient to implement **full blown** type reflection, that's what we're talking about here ... – πάντα ῥεῖ Feb 06 '14 at 17:10
  • @Chris RTTI is only very minimalistic and IMO only useful for `dynamic_cast` and some factory mapping – Sebastian Hoffmann Feb 06 '14 at 17:11
  • 1
    Via you can get std::typeid this will give you access to std::cout << typeid(myClass.mick).name() << std::endl; which will give you the name of the type. – Chris Feb 06 '14 at 17:19
  • 1
    I don't understand the horse/helecopter analogy. – Chris Feb 06 '14 at 17:22
  • @Chris Now please tell me, how do you iterate over all members of type `T` with RTTI/typeid? – Sebastian Hoffmann Feb 06 '14 at 17:23
  • @Paranaix - The 'solution' you give requires prior knowledge and worse, modification of the existing class. In answer to "Now please tell me, how do you iterate over all members of type T with RTTI/typeid?" I don't know how, that's why I asked the original question - I would have thought that was pretty obvious. – Chris Feb 06 '14 at 17:40
  • 1
    @Chris And I told oyu its is not possible, but provided a workaround – Sebastian Hoffmann Feb 06 '14 at 17:44
  • It's not an effective workaround, I'm working with legacy code and I'm not about to write static maps for all the classes I wish to deal with. Thanks for your input though. – Chris Feb 06 '14 at 17:49
  • @Chris _'I'm working with legacy code'_ No chance then! Wasn't that clear from the answers?? – πάντα ῥεῖ Feb 06 '14 at 18:50
  • @Chris Please refer to my more advanced solution. By utilizing template specialization it allows to implement this feature for legacy code aswell. – Sebastian Hoffmann Feb 06 '14 at 18:51
  • @Chris _I don't understand the horse/helecopter analogy._ The point is: **Horses don't have wings**! (replace 'horse' with 'c++-classes' and 'wings' with 'reflection'). – πάντα ῥεῖ Feb 06 '14 at 18:53