Rajat
Rajat

Reputation: 487

template types in std is_member_function_pointer

I am referring to a possible implementation of std::is_member_function_pointer here.

template< class T >
struct is_member_function_pointer_helper : std::false_type {};

template< class T, class U>
struct is_member_function_pointer_helper<T U::*> : std::is_function<T> {};

template< class T >
struct is_member_function_pointer : is_member_function_pointer_helper< std::remove_cv_t<T> >     


#include <type_traits>

class A {
public:
    void member() { }
};



int main()
{
    // fails at compile time if A::member is a data member and not a function
    static_assert(std::is_member_function_pointer<decltype(&A::member)>::value,
                  "A::member is not a member function."); 
}

I know that

"dectype(&A::member)"

will be

"void (A::*)()"

But I dont understand what type T and type U map to in "void (A::*)()"?

Upvotes: 3

Views: 387

Answers (3)

WhiZTiM
WhiZTiM

Reputation: 21576

template< class T, class U>
struct is_member_function_pointer_helper<T U::*> : std::is_function<T> {};

The above specialization will be a match if it were possible to decompose the the primary template argument into a class type U and a non-static member type T. The class type U is no longer useful here, because we've confirmed, its really a class.

The non-static member-type T is then passed as the template argument to std::is_function which has a whole lot of machinery in determining that T is indeed a function.


But I dont understand what type T and type U map to in void (A::*)()?

As explained above, once we are able to decompose void (A::*)() to match T U::* You will find out that A::* maps to U::*. Lets remove that pattern, we are left with void () which is what T will be.

Upvotes: 4

cpplearner
cpplearner

Reputation: 15918

I think it's easier to understand if we first translate the type-id into English. That is, void (A::*)() is translated to "pointer to member of class A of type function of () returning void" and T U::* to "pointer to member of class U of type T". Now if we compare the two type we can see U corresponds to the class A and T corresponds to "function of () returning void", i.e. void().

Upvotes: 2

mpark
mpark

Reputation: 7904

The pattern void (A::*)() decomposes into T U::* where U is A and T is void (). You can see the construction in inverse, like this:

struct A {};

using T = void ();
using U = A;

template <typename> struct print;

int main() {
    print<T U::*>{};
    // error: implicit instantiation of undefined template 'print<void (A::*)()>'
}

So the T as void () is passed to std::is_function which determines whether the given type is a function type.

In the case of pointer to data members, this fails because the deduced T is going to be a non-function type.

Upvotes: 6

Related Questions