5

C++ でオーバーロードされたメンバー関数へのポインターを処理する際に小さな問題があります。次のコードは正常にコンパイルされます。

class Foo {
public:
    float X() const;
    void X(const float x);
    float Y() const;
    void Y(const float y);
};

void (Foo::*func)(const float) = &Foo::X;

しかし、これはコンパイルされません (コンパイラはオーバーロードがあいまいであると不平を言います):

void (Foo::*func)(const float) = (someCondition ? &Foo::X : &Foo::Y);

おそらくこれは、コンパイラが条件演算子の戻り値を関数ポインタ型とは別に分類することに関係しているのでしょうか? 私はそれを回避することができますが、仕様がどのように機能することになっているのかを知りたいと思っています。 .

それが違いを生む場合、私はMSVC ++を使用しています。

ありがとう!

4

3 に答える 3

7

セクション 13.4/1 (「オーバーロードされた関数のアドレス」[over.over]) から:

オーバーロードされた関数名を引数なしで使用すると、関数、関数へのポインター、またはオーバーロード セットからの特定の関数のメンバー関数へのポインターへの特定のコンテキストで解決されます。関数テンプレート名は、そのようなコンテキストでオーバーロードされた関数のセットに名前を付けると見なされます。選択された関数は、そのタイプがコンテキストで必要なターゲット タイプと一致するものです。ターゲットは

  • 初期化されているオブジェクトまたは参照 (8.5、8.5.3)、
  • 割り当ての左側 (5.17)、
  • 関数のパラメータ (5.2.2)、
  • ユーザー定義演算子のパラメーター (13.5)、
  • 関数、演算子関数、または変換 (6.6.3) の戻り値、または
  • 明示的な型変換 (5.2.3、5.2.9、5.4)。

オーバーロード関数名の前に&演算子を付けることができます。オーバーロードされた関数名は、リストされているもの以外のコンテキストでは引数なしで使用してはなりません。[注:オーバーロードされた関数名を囲む冗長な括弧のセットは無視されます (5.1)。]

上記のリストから選択されることを望んでいたターゲットは、初期化されている最初のオブジェクトでした。しかし、途中で条件演算子があり、条件演算子は対象の型からではなく、オペランドから型を決定します。

ターゲットのリストには明示的な型変換が含まれているため、条件式の各メンバー ポインター式を個別に型キャストできます。最初に typedef を作成します。

typedef void (Foo::* float_func)(const float);
float_func func = (someCondition ? float_func(&Foo::X) : float_func(&Foo::Y));
于 2009-09-14T23:02:03.413 に答える
1

例:

class Foo {
public:
    void X(float x) {}
    void Y(float y)  {}
    float X() const;
};
typedef void (Foo::*Fff)(float);
Fff func = &Foo::X;
Fff func2 = true ? (Fff)&Foo::X : (Fff)&Foo::Y;

int main(){
    return 0;
}

オーバーロードを解決するには、すぐに &Foo::X をキャストする必要があります。オーバーロードされた float X() をコメント アウトする場合は、コメント アウトする必要がないことに注意してください。

コンパイラは、必要な三項式の戻り値の型を推測するほど賢くないようです (これはバグの可能性があります)。

于 2009-09-14T22:51:58.633 に答える
1

試す:

    void (Foo::*func1)(const float) = &Foo::X;
    void (Foo::*func2)(const float) = &Foo::Y;

    void (Foo::*func3)(const float) = (someCondition ? func1:func2);

問題は、演算子 trinary の結果の型がその引数によって決定されることです。
この状況では、入力タイプに複数のオプションがあるため、結果のタイプを判別できません。三項演算子の型が決定されるまで、代入は行われません。

于 2009-09-14T23:05:05.747 に答える