名前空間
変種
操作

オーバーロードされた関数のアドレス

From cppreference.com
< cpp‎ | language
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

オーバーロード解決が行われる関数呼び出し式の他に、オーバーロードされた関数の名前は次の7つのコンテキストに現れることがあります。

コンテキスト ターゲット
オブジェクトまたは参照宣言における初期化子 初期化されるオブジェクトまたは参照
代入式の右辺 代入の左辺
関数呼び出しの引数として 関数パラメータ
ユーザー定義演算子の引数として 演算子パラメータ
return 関数または変換の戻り値
明示的なキャストまたはstatic_cast 引数 対応するキャスト
非型テンプレート引数 対応するテンプレートパラメータ

各コンテキストにおいて、オーバーロードされた関数の名前の前にはアドレス演算子 & が置かれ、冗長な括弧で囲むことができます。

ターゲット型がプレースホルダー型を含む場合、プレースホルダー型推論が実行され、以下の記述では推論された型をターゲット型として使用します。

(C++26以降)

目次

[編集] 関数の選択

オーバーロードされた関数のアドレスが取られるとき、オーバーロード関数の名前によって参照されるオーバーロードセットから、関数のセット S が選択されます。

  • ターゲットがない場合、名前付きの非テンプレート関数がすべて選択されます。
  • そうでない場合、ターゲット型の関数型 FT に対して、型 F の非テンプレート関数が選択されます。ただし、F (おそらく関数ポインタ変換を適用した後)(C++17以降)FT と同一である場合です。[1]
  • 各名前付き関数テンプレートに対するテンプレート引数推論によって生成された特殊化 (もしあれば) も S に追加されます。

ターゲットが関数ポインタ型または関数への参照型である場合、S には非メンバ関数、明示的なオブジェクトメンバ関数(C++23以降)、および静的メンバ関数のみを含めることができます。ターゲットがメンバ関数へのポインタ型である場合、S には暗黙的なオブジェクトメンバ関数のみを含めることができます。

  1. 言い換えれば、ターゲット型がメンバ関数へのポインタ型である場合、関数が属するクラスは無視されます。

[編集] 関数の除外

セット S を形成した後、関数は以下の順序で除外されます。

  • 関連する制約が満たされていないすべての関数は、S から除外されます。
(C++20以降)
  • S に複数の関数が残っている場合、S に非テンプレート関数も含まれているときは、S 内のすべての関数テンプレート特殊化が除外されます。
  • S に、与えられた非テンプレート関数 func よりも部分順序制約がより強い2番目の非テンプレート関数が含まれている場合、その与えられた非テンプレート関数 func は除外されます。
(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]
English 日本語 中文(简体) 中文(繁體)