2009-09-14 11 views
5

Mam niewielki problem dotyczący wskaźników do przeciążenia funkcji składowych w C++. Poniższy kod kompiluje grzywny:Operator warunkowy nie może rozpoznać przeciążonych wskaźników funkcji elementu

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; 

Ale to nie kompiluje (kompilator narzeka, że ​​przeciążenia są niejednoznaczne):

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

Przypuszczalnie jest to coś zrobić z kompilator sortowaniu powrót wartość operatora warunkowego niezależnie od typu wskaźnika funkcji? Mogę to obejść, ale chciałbym się dowiedzieć, jak to mówią, że wszystko to ma działać, ponieważ wydaje się mało intuicyjne i jeśli jest jakaś metoda obejścia go bez cofania się do 5 linii .

Używam MSVC++, jeśli to robi jakąkolwiek różnicę.

Dzięki!

+1

Należy wskazać, co oznacza "nie działa". Błąd kompilatora? Nieoczekiwane zachowanie środowiska wykonawczego? –

+0

Zrobiłem to, dzięki za sugestię. – Peter

Odpowiedz

7

Z sekcji 13.4/1 („Adres funkcji przeciążonej” [over.over]):

Zastosowanie przeciążonej nazwy funkcji bez argumentów został rozwiązany w pewnych kontekstach do funkcji, wskaźnik do funkcji lub wskaźnika do funkcji składowej dla określonej funkcji z zestawu przeciążeniowego. Nazwa szablonu funkcji jest uważana za nazwę zestawu przeciążonych funkcji w takich kontekstach. Wybrana funkcja jest tą, której typ odpowiada typowi docelowemu wymaganemu w kontekście. Celem może być

  • przedmiot lub odniesienia inicjowany (8.5, 8.5.3)
  • lewa strona przypisania (5,17)
  • parametrem funkcji (5.2.2) ,
  • parametrem operatora zdefiniowany przez użytkownika (13,5)
  • wartość zwracanej przez funkcję, funkcję operatora, lub zamiany (6.6.3) lub
  • jednoznaczne przekształcenie typu (5.2.3, 5.2.9, 5.4).

Nazwa funkcji przeciążenia może być poprzedzona operatorem &. Nazwa przeciążonej funkcji nie może być używana bez argumentów w kontekstach innych niż wymienione. [Uwaga: każdy nadmiarowy zestaw nawiasów otaczających nazwę przeciążonej funkcji jest ignorowany (5.1). ]

Cel pan nadzieję, że być wybrany z powyższej listy był pierwszym, obiekt jest zainicjowany. Ale na drodze jest operator warunkowy, a operatory warunkowe określają swoje typy z ich operandów, a nie z dowolnego typu celu.

Ponieważ konwersje typu jawnego znajdują się na liście celów, można rzutować oddzielnie każde wyrażenie wskaźnika członu w wyrażeniu warunkowym. Chciałbym zrobić pierwszy typedef:

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

Dzięki, że działa idealnie - właśnie to, na co liczyłem. – Peter

1

Przykład:

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

Trzeba rzucić & Foo :: X natychmiast w celu rozwiązania przeciążenie. Zwróć uwagę, że jeśli skomentujesz przeciążony float X(), nie musisz tego robić.

Wygląda na to, że kompilator nie jest wystarczająco inteligentny, aby wywnioskować wymagany typ zwrotu potrójnego wyrażenia (może to być błąd).

+0

someCondition nie jest stałą czasu kompilacji, chociaż prawdopodobnie nie było to całkowicie oczywiste z uproszczonego przykładu, który dałem. Mogę ewentualnie zamienić go w szablon poprzez szablon, ale myślę, że byłby brzydszy ogólnie ... :) – Peter

+1

I tak nie musi być jeden. –

1

Spróbuj:

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

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

Problemem jest typem wynikiem Trójka operatora jest określana przez jej argumentów.
W tej sytuacji nie można określić typu wyniku, ponieważ typy wejściowe mają wiele opcji. Dopóki typ operatora trójstronnego nie zostanie określony, będzie próbował wykonać zadanie.

Powiązane problemy