为什么安培和安培对于引用呼叫接线员是必要的

Why Is Ampersand Necessary For Referencing The Call Operator

本文关键字:接线员 呼叫 于引用 为什么 引用      更新时间:2023-10-16

我认为C++规范规定,在引用函数时,函数前面的"与"符号是不必要的,即

void bar();
void foo(void(*bar)());
foo(bar);
foo(&bar);  // Same as above.

然而,我发现了一个事实并非如此。我试图对lambda(仅限单个参数)进行模板专门化,这样我就可以访问lambda的返回参数和输入参数的类型。

// The ampersand in front of 'Fn::operator()' is necessary to make
// this code work.
template <typename Lambda>
struct Signature : public Signature<decltype(&Fn::operator())> {};
template <typename ClassT, typename RetT, typename ArgT>
struct Signature<RetT(ClassT::*)(ArgT) const> {
  using ReturnType = RetT;
  using ArgumentType = ArgT;
};

没有安培数,叮当抱怨

error: call to non-static member function without an object argument
struct Signature : public Signature<decltype(Fn::operator())> {};
                                             ~~~~^~~~~~~~

我得到了可以工作的代码,但我想了解它为什么工作。为什么这里需要安培数和?

要获取成员函数的地址,必须始终在其前面加上&(与号)。这不仅适用于模板和/或lambda,也适用于C++中的任何成员函数。

至于为什么,我们只能推测。但C++一直都是这样。也许C兼容性是允许为免费函数省略&的唯一原因。

指向函数的指针和指向成员函数的指针是不同的野兽。虽然函数衰减为指向函数的指针,但对于成员函数或成员对象,情况并非如此。虽然有标准的函数到指针转换,但成员函数或成员对象没有类似的功能。当您想要获得指向成员的指针时,您总是需要使用&

我不知道确切的原因,但我怀疑操作员的地址是为了避免有时出现在功能中的错误,例如:

int f();
// ...
if (f) { // always true
}

虽然从函数到函数指针的隐式转换不能在不破坏C兼容性的情况下删除,但当引入成员和指向成员的指针时,就没有类似的问题了。