名稱空間
變體
操作

過載函式地址

來自 cppreference.com
< cpp‎ | 語言
 
 
C++ 語言
 
 

除了發生過載決議函式呼叫表示式之外,過載函式的名稱可以出現在以下 7 種語境中

語境 目標
物件或引用宣告中的初始化器 被初始化的物件或引用
賦值表示式的右側 賦值表示式的左側
作為函式呼叫引數 函式引數
作為使用者定義運算子引數 運算子引數
return 語句 函式或轉換的返回值
顯式轉換static_cast 引數 相應的轉換
非型別模板引數 相應的模板引數

在每個語境中,過載函式的名稱前面可以帶有取址運算子 &,並且可以被一對多餘的括號括起來。

如果目標型別包含佔位符型別,則執行佔位符型別推導,以下描述使用推導型別作為目標型別。

(C++26 起)

目錄

[編輯] 選擇函式

當取一個過載函式的地址時,會從由過載函式名稱引用的過載集中選擇一個函式集合 S

  • 如果沒有目標,則選擇所有非模板函式。
  • 否則,如果型別為 F 的非模板函式(在可能應用函式指標轉換後)(C++17 起)與目標型別的函式型別 FT 相同,則選擇該函式。[1]
  • 透過對每個命名的函式模板進行模板引數推導所生成的特化(如果有)也被新增到 S 中。

如果目標是函式指標型別或函式引用型別,則 S 只能包含非成員函式、顯式物件成員函式(C++23 起)和靜態成員函式。如果目標是指向成員函式指標型別,則 S 只能包含隱式物件成員函式。

  1. 換句話說,如果目標型別是指向成員函式指標型別,則忽略該函式所屬的類。

[編輯] 消除函式

形成集合 S 後,按以下順序消除函式

  • 所有具有不滿足的關聯約束的函式都從 S 中消除。
(C++20 起)
  • 如果 S 中剩下多個函式,則如果 S 也包含非模板函式,則消除 S 中的所有函式模板特化。
  • 如果 S 包含第二個非模板函式,其偏序約束比給定非模板函式 func 更強,則消除 func
(C++20 起)
  • 如果 S 包含第二個函式模板特化,其函式模板比給定函式模板特化 spec 的函式模板更特化,則消除 spec

在這樣的消除(如果有)之後,S 中應該恰好剩下一個選定的函式。否則,程式格式不正確。

[編輯] 示例

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++ 標準。

缺陷報告 應用於 釋出時的行為 正確的行為
CWG 202 C++98 非型別模板引數不是
取過載函式地址的語境
它是
CWG 250 C++98 使用非推導模板引數生成的函式模板特化
未從過載集中選擇
也選擇
CWG 1153 C++98 不清楚給定函式型別是否與目標型別匹配 已明確
CWG 1563 C++11 不清楚列表初始化是否是一個語境
取過載函式地址的語境
已明確

[編輯] 參考資料

  • 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]