3
struct X
{
    void f(double) {}
    static void f(int) {}
};

int main()
{
    X x;

    auto y = x.f;
}

gcc は次のように与えます:

error: unable to deduce ‘auto’ from ‘x.X::f’

x.f5.2.5 [expr.ref] に記載されているクラス メンバー アクセスです。 postfix-expression

それは効果的に言います:

が (オーバーロードされている可能性がある) メンバー関数である場合、関数のオーバーロード解決 (13.3) を使用して、静的メンバー関数または非静的メンバー関数のどちらを参照しているfかを判断します。x.f(N3485 5.2.5.4.3 より)

ここでオーバーロード解決を適用するにはどうすればよいですか -x.fオーバーロード解決を行うためのパラメーター リストがありませんか?

または、何か不足していますか?

更新:auto y = x.f行を次のように変更するとexpression-statement:

- auto y = x.f;
+ x.f;

次に、gcc は代わりに文句を言います。

error: statement cannot resolve address of overloaded function
4

2 に答える 2

3

この時点で標準が正確ではないという点で、あなたは正しいと思います。

[expr.ref]/4

f が (オーバーロードされている可能性がある) メンバー関数である場合、関数のオーバーロードの解決 (13.3) を使用しx.fて、静的メンバー関数または非静的メンバー関数のどちらを参照しているかを判断します。

最初のサブブレットが述べているように:

静的メンバ関数を参照し、E2 の型が「T を返すパラメータ型リストの関数」である場合、E1.E2 は左辺値です。式は静的メンバー関数を指定します。E1.E2 の型は E2 と同じ型、つまり「T を返す parameter-type-list の関数」です。

つまり、が static のx.f場合は関数 ptr を初期化するために使用できますがf、(次のサブ箇条書きを参照)fが static でない場合は、関数呼び出し式でのみ使用できます。

しかし実際には、オーバーロード解決は、関数呼び出し式のコンテキスト外でオーバーロードされた関数の名前からオーバーロードを選択するために実行されません。

[オーバー.オーバー]/1

オーバーロードされた関数名を引数なしで使用すると、特定のコンテキストで関数、関数へのポインター、またはオーバーロード セットの特定の関数のメンバー関数へのポインターに解決されます。[...]選択された関数は、コンテキストで必要なターゲット型の関数型と同じ型の関数です。

つまり、[over.match] で説明されているオーバーロード解決メカニズムを呼び出さない完全一致です。x.fしたがって、[expr.ref]/4 は不完全であり、関数ポインター/参照を初期化するために使用するケースについて説明していません。

autoキーワードがターゲット タイプを指定していないため (または [dcl.spec.auto]/6、失敗のタイプを推測するメカニズムによると) auto、次を使用できませんauto y = x.f;

  • x.fオーバーロードされた関数のセットを参照します
  • このセットから機能を選択する必要があります
  • 選択は、オーバーロードの解決 (ここでは適用されない関数呼び出し式内) またはターゲットの型に基づいています。
  • ここにはターゲット型がありません。または、ターゲット型はテンプレート引数と同等であるため、auto失敗の型推定

x.fしたがって、の型は

  • 関数呼び出しのコンテキストでは、[expr.ref]/4 を直接参照します。
  • それ以外の場合は、オーバーロードされた関数のセットであり、[over.over] に従って関数が選択され、[expr.ref]/4 に従って型が決定されます。
于 2013-05-14T12:57:52.483 に答える