成员函数的模板推导

template deduction of member functions

我正在尝试通过常规函数、指向常规函数的指针、成员函数和指向成员函数的指针来理解模板参数推导。有人可以解释为什么最后一行产生编译错误而独立没有问题吗?

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

问题 是我们无法将引用传递给成员,因为来自 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++.

这意味着我们必须显式在调用表达式中使用运算符的地址来传递一个指向成员的指针(因为引用不允许加入会员),如下图:

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

旁注

虽然与您的情况无关,但请注意,与普通函数指针不同,成员函数和指向该成员的指针之间没有自动转换。也就是说,在成员函数的情况下以及在需要(允许)指针的上下文中,表达式 A::fun&A::fun 不等价的 .

Non-static 成员函数与自由函数有很大的不同。它们只能以非常有限的方式使用。

non-static 成员函数的唯一可能用途是在成员访问表达式中调用函数或作为 & 的操作数以形成 pointer-to-member.

A::fun 如果前面没有 & 或成员访问运算符,则表达式本身甚至在语法上都不正确。 decltype(A::fun) 也是 ill-formed。

对于独立函数,指向函数的指针可以根据上下文转换为函数引用,例如为了被调用。函数可以转换为指向自身的指针。结果这两行都是合法且相等的。

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

对于每颗星,它的参数都是一个引用,并根据上下文转换为一个指针,结果将是一个引用,依此类推。在 C++ 中,函数(引用)是一种类型。

表达式 &standalone 明确地是一个指针,因此 what(&standalone); 将使用指针。

现在,指向成员的指针是一种不同于普通指针的类型,并且没有类似的引用形式。获取指向成员函数或成员变量的指针的唯一合法方法是将一元 operator& 与其嵌套名称组合。