Frage

Ich habe ein kleines Problem mit Zeigern auf überladene Elementfunktionen in C ++ zu tun. Der folgende Code kompiliert fein:

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;

Aber das ist nicht kompilieren (der Compiler beschwert sich, dass die Überlastung nicht eindeutig sind):

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

Vermutlich ist dies etwas mit dem Compiler den Rückgabewert des bedingten Operator getrennt von der Funktion Zeigertyp Aussortieren zu tun? Ich kann es umgehen, aber ich bin daran interessiert zu wissen, wie die Spezifikation sagt das alles funktionieren soll, da es ein wenig unintuitive scheint und wenn es einen Weg, um es zu arbeiten, ohne zu 5 Zeilen if-then-else zu fallen zurück .

Ich bin mit MSVC ++, wenn das einen Unterschied macht.

Danke!

War es hilfreich?

Lösung

Aus dem Bereich 13,4 / 1 ( "Adresse der überladenen Funktion" [over.over]):

  

Eine Verwendung eines überladenen Funktionsnamen ohne Argumente wird in bestimmten Zusammenhängen zu einer Funktion, einen Zeiger auf Funktion oder Zeiger auf Elementfunktion für eine bestimmte Funktion von dem Überlastsatz aufgelöst. Eine Funktion Template-Name wird als eine Reihe von überladenen Funktionen in solchen Kontexten zu nennen. Die ausgewählte Funktion ist derjenige, dessen Typ entspricht den Zieltyp in Rahmen erforderlich. Das Ziel kann sein

     
      
  • ein Objekt oder eine Referenz initialisiert wird (8.5, 8.5.3),
  •   
  • die linke Seite einer Zuweisung (5,17),
  •   
  • ein Parameter einer Funktion (5.2.2),
  •   
  • ein Parameter eines benutzerdefinierten Operator (13.5),
  •   
  • der Rückgabewert einer Funktion, Bedienerfunktion oder Umwandlung (6.6.3) oder
  •   
  • eine explizite Typumwandlung (5.2.3, 5.2.9, 5.4).
  •   
     

Die Überlastfunktion Name kann vom & Operator vorangestellt werden. Ein überladener Funktionsname darf nicht ohne Argumente in anderen Zusammenhängen als die aufgeführten verwendet werden. [ Hinweis: jeder redundanter Satz Klammern der überladenen Funktionsnamen umgeben, wird ignoriert (5.1). ]

Die target Sie hatten gehofft, aus der obigen Liste ausgewählt werden würde, war das erste, ein Objekt initialisiert wird. Aber es gibt einen Bedingungsoperator in der Art und Weise, und bedingte Betreiber bestimmen, deren Typen von ihren Operanden, nicht von jedem Zieltyp.

Da explizite Typkonvertierungen in der Liste der Ziele enthalten sind, können Sie jeden Element-Zeiger Ausdruck im bedingten Ausdruck separat-Typ gegossen. Ich habe gerne einen typedef macht zuerst:

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

Andere Tipps

Versuchen:

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

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

Das Problem ist der Ergebnistyp des Betreibers trinary durch seine Argumente bestimmt wird.
In dieser Situation kann es nicht den Ergebnistyp bestimmen, da die Eingangstypen multuiple Optionen. Erst wenn der Typ des trinary Betreiber bestimmt wurde, dass es die Aufgabe versuchen wird.

Beispiel:

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;
}

Sie müssen gegossen & Foo :: X sofort, um die Überlastung zu lösen. Beachten Sie, wenn Sie die überladene Schwimmer X Kommentar aus (), die Sie nicht so tun müssen.

Es sieht aus wie der Compiler nicht intelligent genug ist, um den erforderlichen Rückgabetyp eines ternären Ausdrucks zu schließen (dies kann ein Problem sein).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top