Home > OS >  template deduction of member functions
template deduction of member functions

Time:04-03

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);
      |             ^~~
}

CodePudding user response:

For a standalone function, a pointer to function can be converted contextually to function reference, e.g. 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.

CodePudding user response:

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.

CodePudding user response:

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.

  • Related