Yay, ein weiterer Fragentitel, der sich aus einer zufälligen Folge von C ++ - Begriffen zusammensetzt!
Normalerweise machen wir eine Klasse Callable, indem wir operator()
implementieren. Sie können dies aber auch tun, indem Sie eine benutzerdefinierte Konvertierung in Funktionszeiger oder Referenztyp implementieren. Anstatt eine perfekte Weiterleitung zu verwenden, kann eine Konvertierungsfunktion einen Zeiger auf eine Funktion zurückgeben, die dann mit der ursprünglichen Argumentliste aufgerufen wird.
Soweit ich das beurteilen kann, ist das oben angegebene typedef
eine syntaktische Notwendigkeit. Der Name einer Konvertierungsfunktion wird aus einem type-specifier-seq gebildet, der kein Konstrukt wie int (*)()
zulässt. Das würde einen abstrakten Deklarator erfordern . Vermutlich liegt der Grund darin, dass solche Typnamen kompliziert werden und komplexe Konstrukte, die als Objektnamen verwendet werden, schwer zu parsen sind.
Konvertierungsfunktionen können auch als Templates verwendet werden, aber die Template-Argumente müssen abgeleitet werden, da sie nirgends explizit angegeben werden können. (Das würde den ganzen Punkt der impliziten Konvertierung besiegen.)
Frage 1: Gibt es in C ++ 03 keine Möglichkeit, eine Funktionskonvertierungsoperatorvorlage anzugeben? Es scheint, dass es keine Möglichkeit gab, die Vorlagenargumente in einem akzeptablen Funktionszeigertyp aufzulösen (d. H. Sie in einem abgeleiteten Kontext zu benennen).
Hier ist der entsprechende Verweis von C ++ 11, §13.3.1.1.2 / 2 [over.call.object]. Es ist im Wesentlichen das gleiche von C ++ 03:
Darüber hinaus für jede nicht explizite Konvertierungsfunktion, die in T der Form
deklariert ist %Vor%wobei cv-qualifier die gleiche cv-qualification wie oder eine größere cv-qualification als cv , und where Conversion-Type ist -id bezeichnet den Typ "Zeiger auf Funktion von (P1, ..., Pn), der R", oder den Typ "Verweis auf Zeiger auf Funktion von (P1, ..., Pn) zurückgibt Zurückgeben von R "oder des Typs" Verweis auf die Funktion von (P1, ..., Pn), der R "zurückgibt, eine Hilfsaufruffunktion mit dem eindeutigen Namen Aufruffunktion und der Form
%Vor%wird auch als Kandidatenfunktion betrachtet. In ähnlicher Weise werden Ersatz-Call-Funktionen zu dem Satz von Kandidatenfunktionen für jede nicht-explizite Konvertierungsfunktion hinzugefügt, die in einer Basisklasse von T deklariert ist, vorausgesetzt, die Funktion wird nicht durch eine andere dazwischenliegende Deklaration in T versteckt.
Frage 2: Kann eine solche Konvertierung in C ++ 11 mit einem Standard-Template-Argument angegeben werden? Dies ist nützlich für SFINAE. Der einzige Unterschied zum obigen Beispiel besteht darin, dass die Conversion-Type-ID nur eine Funktionsreferenz nach der Instanziierung darstellt, da sie ein abhängiger Typ ist (trotz Invarianz). Dies stolpert GCC und es überspringt die Mitgliedervorlage.
%Vor% Wir haben auch Alias-Vorlagen. Es scheint, dass die Alias-Substitution vor der Instanziierung auftritt, in dem Beispiel in § 14.5.7 / 2, wo die Deklarationen von process
in Konflikt stehen. In GCC 4.7 instanziiert dieser Code mindestens die Deklaration, aber dann erzeugt es einen bizarren "Kandidat erwartet 2 Argumente, 2 vorausgesetzt" -Fehler.
Frage 1: In C ++ 03 gab es keine Möglichkeit, eine Funktionskonvertierungsoperatorvorlage anzugeben? Es scheint, dass es keine Möglichkeit gab, die Vorlagenargumente in einem akzeptablen Funktionszeigertyp aufzulösen (d. H. Sie in einem abgeleiteten Kontext zu benennen).
Ja, das ist richtig.
Frage 2: Kann eine solche Konvertierung in C ++ 11 mit einem Standard-Template-Argument angegeben werden?
Es kann, und Sie können auch Alias-Vorlagen verwenden, aber Sie können eine solche Umwandlungsfunktionsvorlage nicht zum Erstellen von Ersatzaufruffunktionen verwenden. Sie können es verwenden, um Ihr Klassenobjekt andernfalls in implizite Konvertierungen in Funktionszeiger zu konvertieren.
Wir haben auch Alias-Vorlagen. Es scheint, dass die Alias-Substitution vor der Instanziierung auftritt, in dem Beispiel in § 14.5.7 / 2, wo die Deklarationen des Prozesskonflikts stehen. In GCC 4.7 instanziiert dieser Code mindestens die Deklaration, aber dann erzeugt es einen bizarren "Kandidat erwartet 2 Argumente, 2 vorausgesetzt" -Fehler.
Ja, dies ist Ссылка (und hat zum Schließen von DR395 geführt ), obwohl eine solche Umwandlungsfunktionsvorlage in Fällen wie void(&p)() = yourClassObject
funktionieren kann, funktioniert sie nicht für Ersatzaufruffunktionen, da dort die Konvertierungsfunktion einen festen nicht abhängigen Typ bereitstellen muss, in den das Klassenobjekt konvertiert wird wenn die Ersatzfunktion aufgerufen wird, aber eine Umwandlungsfunktionsvorlage einen solchen Typ normalerweise nicht bereitstellt (seltsame Dinge wie template<typename = int> operator Identity<void(*)()>();
beiseite ...).
Ich denke, dass GCC fälschlicherweise den Kandidaten call-function(void (&)( t ), t)
mit den abhängigen Typen immer noch erzeugt und versucht, diesen Kandidaten aufzurufen, wodurch er eine Invariante davon verletzt (was die seltsame Fehlermeldung erklären könnte) und möglicherweise unerwartet auf eine } else { ... }
trifft irgendwo).
Tags und Links c++ c++11 type-conversion templates functor