命名空间
变体
操作

重载函数的地址

来自 cppreference.com
< cpp‎ | 语言
 
 
C++ 语言
 
 

除了 函数调用表达式,其中进行 重载解析,重载函数的名称可能会出现在以下 7 种上下文中

# 上下文 目标
1 初始化器声明 对象或 引用 正在初始化的对象或引用
2 在赋值表达式的右侧 赋值的左侧
3 作为函数调用参数 函数参数
4 作为用户定义的运算符参数 运算符参数
5 the return 语句 函数的返回类型
6 显式强制转换static_cast 参数 强制转换的目标类型
7 非类型 模板参数 模板参数的类型

在每种情况下,重载函数的名称前面都可以加上取地址运算符 &,并且可以包含在一个冗余的括号集中。

在所有这些情况下,从重载集中选择的函数是其类型与目标所期望的指向函数的指针、指向函数的引用或指向成员函数的指针类型匹配的函数。

函数的参数类型和返回类型必须与目标完全匹配。不考虑任何隐式转换(例如,返回指向派生类的指针的函数在初始化指向返回指向基类的指针的函数的指针时不会被选中)。

如果函数名称命名了一个函数模板,那么首先,进行 模板参数推断,如果成功,则会生成一个单独的模板特化,并将其添加到要考虑的重载集中。 所有与之相关的 约束 不满足的函数都将从集合中删除。(自 C++20 起) 如果集合中的多个函数与目标匹配,并且至少有一个函数是非模板函数,则模板特化将从考虑范围内删除。 对于任何一对非模板函数,如果其中一个函数比另一个函数 约束更强,则约束较弱的函数将从集合中删除(自 C++20 起)。如果所有剩余的候选者都是模板特化,则如果存在更专业化的候选者,则会删除 不太专业化的 候选者。如果在删除后仍然存在多个候选者,则程序将形成错误。

[编辑] 示例

int f(int) { return 1; }
int f(double) { return 2; }
 
void g(int(&f1)(int), int(*f2)(double)) { f1(0); f2(0.0); }
 
template<int(*F)(int)>
struct Templ {};
 
struct Foo
{
    int mf(int) { return 3; }
    int mf(double) { return 4; }
};
 
struct Emp
{
    void operator<<(int (*)(double)) {}
};
 
int main()
{
    // 1. initialization
    int (*pf)(double) = f; // selects int f(double)
    int (&rf)(int) = f; // selects int f(int)
    int (Foo::*mpf)(int) = &Foo::mf; // selects int mf(int)
 
    // 2. assignment
    pf = nullptr;
    pf = &f; // selects int f(double)
 
    // 3. function argument
    g(f, f); // selects int f(int) for the 1st argument
             // and int f(double) for the second
 
    // 4. user-defined operator
    Emp{} << f; //selects int f(double)
 
    // 5. return value
    auto foo = []() -> int (*)(int)
    {
        return f; // selects int f(int)
    };
 
    // 6. cast
    auto p = static_cast<int(*)(int)>(f); // selects int f(int)
 
    // 7. template argument
    Templ<f> t;  // selects int f(int)
 
    // prevent "unused variable" warnings as-if by [[maybe_unused]]
    [](...){}(pf, rf, mpf, foo, p, t);
}

[编辑] 参考

  • C++23 标准 (ISO/IEC 14882:2024)
  • 12.3 重载函数的地址 [over.over]
  • C++20 标准 (ISO/IEC 14882:2020)
  • 12.5 重载函数的地址 [over.over]
  • C++17 标准 (ISO/IEC 14882:2017)
  • 16.4 重载函数的地址 [over.over]
  • C++14 标准 (ISO/IEC 14882:2014)
  • 13.4 重载函数的地址 [over.over]
  • C++11 标准 (ISO/IEC 14882:2011)
  • 13.4 重载函数的地址 [over.over]
  • C++98 标准 (ISO/IEC 14882:1998)
  • 13.4 重载函数的地址 [over.over]