Search code examples
c++templatestype-traitsmember-pointers

How to get object type of pointer to non-static data member at compile time?


Suppose we have a simple data class like this:

struct DataObj
{ 
  char member[32];
}

And the type of pointer to the member in the data object:

typedef decltype(&DataObj::member) memberObjPtr;

How can I deduce the type of the member variable the pointer points to? Specifically, how do I get:

typedef myExpression<memberObjPtr>::type myType;
std::is_same<char[32],myType>::value == true

What I tried so far:

std::remove_pointer
std::remove_reference
std::decay

Without success. Is there something like remove_member_object_pointer somewhere hidden in the standard? Which is what I would need but can't seem to find..


Solution

  • Member pointers and regular pointers are completely different types. There is nothing you can add or remove to go from a member pointer to a regular object pointer. You need a dedicated type trait.

    // General case
    // If a type isn't supported by a partial specialization
    //  it will use this case and fail to compile
    template<class T>
    struct mbrptr_to_type;
    
    // Partial specialization that matches any data member pointer type
    // T C::* means "pointer to member of type `T` in class `C`"
    template<class T, class C>
    struct mbrptr_to_type<T C::*> {
        // Save the member type so it can be retrieved
        using type = T;
    };
    
    // Helper alias
    template<class T>
    using mbrptr_to_type_t = typename mbrptr_to_type<T>::type;
    

    Using your test case :

    struct DataObj
    {
        char member[32];
    };
    
    // myType will be char[32]
    using myType = mbrptr_to_type_t<decltype(&DataObj::member)>;
    
    // Verification
    #include <type_traits>
    static_assert(std::is_same<char[32], myType>::value);
    

    Live example : Godbolt