過載函式地址
來自 cppreference.com
除了發生過載決議的函式呼叫表示式之外,過載函式的名稱可以出現在以下 7 種語境中
語境 | 目標 |
---|---|
物件或引用宣告中的初始化器 | 被初始化的物件或引用 |
賦值表示式的右側 | 賦值表示式的左側 |
作為函式呼叫引數 | 函式引數 |
作為使用者定義運算子引數 | 運算子引數 |
return 語句 |
函式或轉換的返回值 |
顯式轉換或 static_cast 引數 |
相應的轉換 |
非型別模板引數 | 相應的模板引數 |
在每個語境中,過載函式的名稱前面可以帶有取址運算子 &
,並且可以被一對多餘的括號括起來。
如果目標型別包含佔位符型別,則執行佔位符型別推導,以下描述使用推導型別作為目標型別。 |
(C++26 起) |
目錄 |
[編輯] 選擇函式
當取一個過載函式的地址時,會從由過載函式名稱引用的過載集中選擇一個函式集合 S
- 如果沒有目標,則選擇所有非模板函式。
- 否則,如果型別為
F
的非模板函式(在可能應用函式指標轉換後)(C++17 起)與目標型別的函式型別FT
相同,則選擇該函式。[1] - 透過對每個命名的函式模板進行模板引數推導所生成的特化(如果有)也被新增到
S
中。
如果目標是函式指標型別或函式引用型別,則 S
只能包含非成員函式、顯式物件成員函式(C++23 起)和靜態成員函式。如果目標是指向成員函式指標型別,則 S
只能包含隱式物件成員函式。
- ↑ 換句話說,如果目標型別是指向成員函式指標型別,則忽略該函式所屬的類。
[編輯] 消除函式
形成集合 S
後,按以下順序消除函式
|
(C++20 起) |
- 如果
S
中剩下多個函式,則如果S
也包含非模板函式,則消除S
中的所有函式模板特化。
|
(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]