c++templatestemplate-argument-deductionmember-variables

Inferring type and class when passing a pointer to data member as a non-type template argument


I need to pass a pointer to data member, its type and the class it's a member of, to a template struct. The following works:

template<typename T, typename Cls, T Cls::*member> struct Member {};
struct Struct { int x; };
Member<int, Struct, &Struct::x>

But it requires to explicitly mention the type (T: int) and the class (Cls: Struct). That should be unnecessary. The compiler should be able to figure those two types out on its own.

In fact it can inferm them if I pass the pointer to data member to a function:

template<typename T, typename Cls> void member( T Cls::*member ) {}
struct Struct { int x; };
member( &Struct::x );

Is it possible to pass a pointer to data member as a non-type template argument, while letting the compiler figure out the type and class?


Solution

  • You can use a helper to get the type of the class and the member from the type of a member pointer:

    template <typename T> struct type_from_member;
    
    template <typename Cls,typename M>
    struct type_from_member<M Cls::*> {
        using class_type = Cls;
        using member_type = M;
    };
    

    Then you can use auto and inherit from the helper:

    template <auto member> struct Mem : type_from_member<decltype(member)> {};
    
    using B = Mem<&Struct::x>;
    
    static_assert( std::is_same_v<B::member_type,int>);
    static_assert( std::is_same_v<B::class_type,Struct>);