简体   繁体   中英

template deduction of member functions

I'm trying to understand template argument deduction with regular functions, pointer to regular functions, member functions and pointer to member functions. Can someone explain why the last line yields a compile error while there is no issue with standalone?

#include <iostream>
#include <type_traits>
 
struct A {
    int fun(float, char) const&;
};
 
void standalone(int, char) {}

template <typename T>
void what(T &&) {
    std::cout << __PRETTY_FUNCTION__ << "\n";
}
 
int main() 
{
    what(standalone); // void what(T&&) [with T = void (&)(int, char)]
    what(decltype(&standalone){}); // void what(T&&) [with T = void (*)(int, char)]
    what(decltype(&A::fun){}); // void what(T&&) [with T = int (A::*)(float, char) const &]
    what(A::fun); // main.cpp: In function 'int main()':
                  // main.cpp:30:13: error: invalid use of non-static member function 'int A::fun(float, char) const &'
      |           // what(A::fun);
      |             ^~~
}

The problem is that we cannot pass a reference to a member because from Pointers to members :

The type “pointer to member” is distinct from the type “pointer”, that is, a pointer to member is declared only by the pointer to member declarator syntax, and never by the pointer declarator syntax. There is no “reference-to-member” type in C++ .

This means that we must explicitly use the address of operator in the call expression to pass a pointer to member instead(since reference to member is not allowed), as shown below:

//-------v---------> must explicitly use address of operator
    what(&A::fun); 

Side note

Although irrelevant in your case, note that unlike ordinary function pointers, there is no automatic conversion between a member function and a pointer to that member. That is, in case of member functions and in contexts where a pointer is expected(allowed) the expressions A::fun and &A::fun are not equivalent .

For a standalone function, a pointer to function can be converted contextually to function reference, eg in order to be called. A function can be converted to a pointer to itself. In result those two lines are both legal and equal.

what(standalone); 
what(*********************************************standalone); // stars!

For every star its argument is a reference and is contextually converted to a pointer, the result would be a reference, and so on. In C++ a function (reference) is a type.

The expression &standalone is explicitly a pointer, so what(&standalone); would be using a pointer.

Now a pointer to member is a type distinct from a usual pointer and has no analog in form of reference. The only legal way to obtain a pointer to member function or member variable is to combine unary operator& with its nested name.

Non-static member functions are very different from free functions. They can only be used in a very limited number of ways.

The only possible uses for a non-static member function are in a member access expression to call the function or as an operand to & to form a pointer-to-member.

A::fun by itself isn't even syntactically correct in an expression if it is not preceded by & or a member access operator. decltype(A::fun) is also ill-formed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM