オーバーロードされた関数のアドレス
From cppreference.com
オーバーロード解決が行われる関数呼び出し式の他に、オーバーロードされた関数の名前は次の7つのコンテキストに現れることがあります。
| コンテキスト | ターゲット |
|---|---|
| オブジェクトまたは参照の宣言における初期化子 | 初期化されるオブジェクトまたは参照 |
| 代入式の右辺 | 代入の左辺 |
| 関数呼び出しの引数として | 関数パラメータ |
| ユーザー定義演算子の引数として | 演算子パラメータ |
return 文 |
関数または変換の戻り値 |
明示的なキャストまたはstatic_cast 引数 |
対応するキャスト |
| 非型テンプレート引数 | 対応するテンプレートパラメータ |
各コンテキストにおいて、オーバーロードされた関数の名前の前にはアドレス演算子 & が置かれ、冗長な括弧で囲むことができます。
|
ターゲット型がプレースホルダー型を含む場合、プレースホルダー型推論が実行され、以下の記述では推論された型をターゲット型として使用します。 |
(C++26以降) |
目次 |
[編集] 関数の選択
オーバーロードされた関数のアドレスが取られるとき、オーバーロード関数の名前によって参照されるオーバーロードセットから、関数のセット S が選択されます。
- ターゲットがない場合、名前付きの非テンプレート関数がすべて選択されます。
- そうでない場合、ターゲット型の関数型
FTに対して、型Fの非テンプレート関数が選択されます。ただし、F(おそらく関数ポインタ変換を適用した後)(C++17以降) がFTと同一である場合です。[1] - 各名前付き関数テンプレートに対するテンプレート引数推論によって生成された特殊化 (もしあれば) も
Sに追加されます。
ターゲットが関数ポインタ型または関数への参照型である場合、S には非メンバ関数、明示的なオブジェクトメンバ関数(C++23以降)、および静的メンバ関数のみを含めることができます。ターゲットがメンバ関数へのポインタ型である場合、S には暗黙的なオブジェクトメンバ関数のみを含めることができます。
- ↑ 言い換えれば、ターゲット型がメンバ関数へのポインタ型である場合、関数が属するクラスは無視されます。
[編集] 関数の除外
セット S を形成した後、関数は以下の順序で除外されます。
|
(C++20以降) |
Sに複数の関数が残っている場合、Sに非テンプレート関数も含まれているときは、S内のすべての関数テンプレート特殊化が除外されます。
|
(C++20以降) |
Sに、与えられた関数テンプレート特殊化 spec の関数テンプレートよりもより特殊化された関数テンプレートを持つ2番目の関数テンプレート特殊化が含まれている場合、その与えられた関数テンプレート特殊化 spec は除外されます。
そのような除外 (もしあれば) の後、S には正確に1つの選択された関数が残るべきです。そうでない場合、プログラムは形式を誤っています。
[編集] 例
このコードを実行
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); }
[編集] Defect reports (欠陥報告)
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| 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 standard (ISO/IEC 14882:2020)
- 12.5 オーバーロードされた関数のアドレス [over.over]
- C++17 standard (ISO/IEC 14882:2017)
- 16.4 オーバーロードされた関数のアドレス [over.over]
- C++14 standard (ISO/IEC 14882:2014)
- 13.4 オーバーロードされた関数のアドレス [over.over]
- C++11 standard (ISO/IEC 14882:2011)
- 13.4 オーバーロードされた関数のアドレス [over.over]
- C++98 標準 (ISO/IEC 14882:1998)
- 13.4 オーバーロードされた関数のアドレス [over.over]