I saw this code snippet in the example on cppreference for std::is_function and I don't understand how it works. Could someone explain to me why U gets deduced as it does in PM_traits?
struct A {
int fun() const&;
};
template<typename>
struct PM_traits {};
template<class T, class U>
struct PM_traits<U T::*> {
using member_type = U;
};
int main() {
using T = PM_traits<decltype(&A::fun)>::member_type; // T is int() const&
}
U T::*
is a type such that when we have U T::* p
, p
points to a member of class T
, and that member is of type U
.
fun
is a function of type int () const &
: a const &
-qualified function taking no parameters and returning int
, and it's a member of class A
. Therefore, in the deduction, T
is deduced to A
and U
is deduced to the type of A::fun
, which is int () const &
.
It may look a bit confusing, because if the type of &A::fun
was spelled out explicitly, it would have to be written int (A::*)() const &
. However, in the template's case, the type int () const &
is "hidden" behind the name U
, so the pointer to member is then just U A::*
. It's similar to how type names can be used to simplify the syntax of normal function pointers:
int foo(char, double) { return 42; }
using Fun = int (char, double);
Fun *p = &foo;
// instead of:
int (*q)(char, double) = &foo;
The same happens in the template, just with A::*
instead of *
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With