L'operatore condizionale non è in grado di risolvere i puntatori di funzione membro sovraccarico

StackOverflow https://stackoverflow.com/questions/1424261

Domanda

Sto riscontrando un piccolo problema con i puntatori a funzioni membro sovraccaricate in C ++. Il seguente codice viene compilato correttamente:

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;

Ma questo non viene compilato (il compilatore si lamenta che i sovraccarichi sono ambigui):

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

Presumibilmente questo ha a che fare con il compilatore che ordina il valore di ritorno dell'operatore condizionale separatamente dal tipo di puntatore a funzione? Posso aggirarlo, ma sono interessato a sapere come le specifiche dicono che tutto ciò dovrebbe funzionare poiché sembra un po 'poco intuitivo e se c'è un modo per aggirarlo senza ricadere su 5 righe di if-then-else .

Sto usando MSVC ++, se questo fa la differenza.

Grazie!

È stato utile?

Soluzione

Dalla sezione 13.4 / 1 (" Indirizzo della funzione sovraccaricata, " [over.over]):

  

L'uso di un nome di funzione sovraccarico senza argomenti viene risolto in alcuni contesti in una funzione, un puntatore a funzione o un puntatore a funzione membro per una funzione specifica dal set di sovraccarico. Un nome di modello di funzione viene considerato come un insieme di funzioni sovraccariche in tali contesti. La funzione selezionata è quella il cui tipo corrisponde al tipo di destinazione richiesto nel contesto. Il target può essere

     
      
  • un oggetto o riferimento in fase di inizializzazione (8.5, 8.5.3),
  •   
  • il lato sinistro di un compito (5.17),
  •   
  • un parametro di una funzione (5.2.2),
  •   
  • un parametro di un operatore definito dall'utente (13.5),
  •   
  • il valore restituito di una funzione, funzione operatore o conversione (6.6.3) o
  •   
  • una conversione di tipo esplicita (5.2.3, 5.2.9, 5.4).
  •   
     

Il nome della funzione di sovraccarico può essere preceduto dall'operatore & amp; . Un nome di funzione sovraccarico non deve essere utilizzato senza argomenti in contesti diversi da quelli elencati. [ Nota: qualsiasi serie di parentesi ridondanti che circonda il nome della funzione sovraccarica viene ignorata (5.1). ]

Il target che speravi fosse selezionato dall'elenco sopra era il primo, un oggetto in fase di inizializzazione. Ma c'è un operatore condizionale nel modo, e gli operatori condizionali determinano i loro tipi dai loro operandi, non da alcun tipo di destinazione.

Poiché le conversioni di tipo esplicito sono incluse nell'elenco delle destinazioni, è possibile eseguire il cast di ogni espressione puntatore-membro nell'espressione condizionale separatamente. Prima farei un typedef:

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

Altri suggerimenti

Prova:

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

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

Il problema è che il tipo di risultato del trinary dell'operatore è determinato dai suoi argomenti.
In questa situazione, non è possibile determinare il tipo di risultato poiché i tipi di input hanno opzioni multipla. Solo quando viene determinato il tipo di operatore trinario che tenterà l'incarico.

Esempio:

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

Devi lanciare & amp; Foo :: X immediatamente per risolvere il sovraccarico. Si noti che se si commenta il float X () sovraccarico, non è necessario farlo.

Sembra che il compilatore non sia abbastanza intelligente da dedurre il tipo di ritorno richiesto di un'espressione ternaria (questo potrebbe essere un bug).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top