Der Template-Parameter ist nicht eindeutig: Das Template-Argument konnte nicht abgeleitet werden

8

Ich mache eine Art Wrapper, der so aussieht:

%Vor%

Und ich bekomme diesen Fehler:

  • Apply : keine übereinstimmende überladene Funktion gefunden.
  • void Apply(void (__thiscall T::* )(Value),T *,Value) : Vorlagenparameter Value ist mehrdeutig, könnte int oder const int & sein.
  • void Apply(void (__thiscall T::* )(Value),T *,Value) : konnte das Template-Argument für Value von const int nicht ableiten.

Also ich verstehe, dass es aus der Template-Parameterableitung kommt, aber ich verstehe nicht, wie. Warum würde Value nicht beide Male const int& auswerten?

    
HiroshimaCC 08.11.2016, 21:44
quelle

2 Antworten

12

Warum es fehlschlägt

Momentan wird der Template-Parameter Value an zwei verschiedenen Stellen im Aufruf von Apply abgeleitet: vom Zeiger zum Elementfunktionsargument und vom letzten Argument. Von &Foo::MyFunc , Value wird als int const& abgeleitet. Von f.GetValue() , Value wird als int abgeleitet. Dies liegt daran, dass Referenz- und Top-Level-CV-Qualifikationsmerkmale für den Vorlagenabzug gelöscht werden. Da diese beiden Abzüge für den Parameter Value unterschiedlich sind, schlägt der Abzug fehl - wodurch Apply() aus der Überladungsmenge entfernt wird, und infolgedessen haben wir keine brauchbare Überladung.

Wie man es repariert

Das Problem ist, dass Value an zwei verschiedenen Stellen abgeleitet wird, also verhindern wir das. Eine Möglichkeit besteht darin, eine der Verwendungen in einen nicht abgeleiteten Kontext zu verpacken:

%Vor%

Das letzte Argument, v , hat den Typ non_deduced_t<Value> , was, wie der Name schon sagt, ein nicht-hergeleiteter Kontext ist. Also wird Value während des Template-Deduktionsprozesses als int const& vom Zeiger auf die Member-Funktion abgeleitet (wie zuvor) und jetzt stecken wir das einfach in den Typ für v .

Alternativ können Sie cb als eigenen Vorlagenparameter ableiten. An diesem Punkt wird Apply() nur auf std::invoke() reduziert.

    
Barry 08.11.2016, 22:05
quelle
3

Der Ausdruck f.GetValue() ist ein Lvalue vom Typ const int . Wenn dieser Wert übergeben wird, leitet der Argumentabzug des Templates den Typ int ab. Im Allgemeinen führt die Ableitung von Value von Value v zu nie zu einer Referenz oder einem Typ mit der höchsten cv-Qualifikation.

Sie werden wahrscheinlich zwei separate Template-Parameter anstelle von Value haben (eine für das Argument des Funktionstyps, eine für den eigentlichen Argumenttyp) und SFINAE verwenden, um Apply zu deaktivieren, wenn cb nicht ist aufrufbar mit v (oder static_assert für einen schweren Fehler).

    
Brian 08.11.2016 21:51
quelle