Zusammenfassung: Ich möchte mit einer Funktion enden, die die exakten Typen ableitet, mit denen sie aufgerufen wurde, und nimmt (zB) ein Tupel, das sie weiterleitet (deren Typen sich von den exakten unterscheiden) Typen, mit denen die Funktion aufgerufen wurde).
Ich bleibe stecken und versuche, die Arten der Argumente für eine gegebene Funktion über den Abzug zu "wissen", während ich sie gleichzeitig weiterleite. Ich denke, dass mir etwas Entscheidendes fehlt, wie das funktioniert.
%Vor% Was ich gerne sehen möchte, ist ein Szenario, in dem meine Funktion (zB g1
oder g2
) aufgerufen wird und beide Originaltypen kennt und verwendet - int,double,void*,std::string&,const char*
und die Weiterleitungen auch.
In diesem Fall scheint ich diese Informationen nicht innerhalb von g1
oder g2
zu finden. Der (absichtliche, zum Ausdrucken der Typen) Linker Fehler zeigt mir in g1
das sind:
und in g2
:
Es gibt zwei Dinge, die ich hier nicht verstehe:
Warum stimmt keiner der gedruckten (über den Linker-Fehler) Typen mit dem überein, was ich tatsächlich übergeben habe? (%Code%). Kann ich ableiten, was ich tatsächlich bestanden habe? Vorzugsweise mit "natürlicher" Syntax, d. H. Alles nur einmal und nichts explizit ausgeschrieben. Ich kann explizit schreiben:
%Vor%aber das ist "unhandlich" um es gelinde auszudrücken!
In int,double,void*,std::string&,const char
Das Vorhandensein von g1
in der Funktionssignaturdeklaration scheint die Typen im Vorlagenparameter &&
selbst zu ändern. Vergleichen Sie das mit:
Oder:
%Vor%Verwenden Sie eines der folgenden mit:
%Vor% ändert nicht den Typ von Args
. Warum ändert der T
den Typ von &&
selbst, wenn T
nicht?
Beantworten Sie die erste Frage:
Argumente für Funktionen sind Ausdrücke , nicht Typen . Der Unterschied zwischen diesen beiden wird in Kapitel 5 [Ausdruck], p5:
ausgedrücktWenn ein Ausdruck anfänglich den Typ "Verweis auf T" hat (8.3.2, 8.5.3), der Typ wird vor jeder weiteren Analyse auf T eingestellt.
Somit gibt es keinen Unterschied zwischen g(str)
und g(sref)
. g()
sieht immer eine std::string
und niemals eine Referenz.
Zusätzlich können Ausdrücke lvalue oder rvalue sein (eigentlich ist das eine Vereinfachung der C ++ 11-Regeln, aber es ist nah genug für diese Diskussion - wenn Sie die Details haben wollen, sind sie in 3.10 [basic.lval]) / p>
Beantworten Sie die zweite Frage:
Template-Parameter des Formulars:
%Vor% sind etwas Besonderes. Sie sind im Gegensatz zu T
, T&
oder sogar const T&&
folgendermaßen:
Wenn T&&
an einen Lvalue bindet, wird T
als Lvalue-Referenztyp abgeleitet, andernfalls wird T
genau nach den normalen Deduktionsregeln abgeleitet.
Beispiele:
%Vor%Dieses Verhalten unterstützt die sogenannte perfekte Weiterleitung , die normalerweise folgendermaßen aussieht:
%Vor% Wenn man foo(A())
(ein rvalue A
) aufruft, wird T
nach normalen Regeln als A
abgeleitet. Innerhalb von foo
wird t
in A&&
(ein rvalue) umgewandelt und bar
aufgerufen. Die Überladung von bar
, die einen rvalue A
annimmt, wird dann gewählt. I.e. Wenn wir foo
mit einem rvalue aufrufen, ruft foo
bar
mit einem rvalue auf.
Aber wenn wir foo(a)
(ein lvalue A
) aufrufen, wird T
als A&
abgeleitet. Jetzt sieht die Besetzung wie folgt aus:
was unter den Referenz-Kollabierungsregeln vereinfacht zu:
%Vor% i.e. Der L-Wert t
wird in einen L-Wert (eine No-Op-Umwandlung) umgewandelt, und somit wird die bar
-Überladung, die einen L-Wert annimmt, aufgerufen. I.e. Wenn wir foo
mit einem Lvalue aufrufen, ruft foo
bar
mit einem Lvalue auf. Und genau hier kommt der Begriff perfekte Weiterleitung .
Typen (auch in C ++) sind meistens ein Kompilierungstyp (außer natürlich die RTTI in VTables).
Wenn Sie vollständig dynamische Typen benötigen, ist C ++ möglicherweise nicht die beste Sprache dafür.
Sie könnten GCC (eigentlich g++
, vorausgesetzt es ist mindestens 4.6) mit einem Plugin oder einem erweitern GCC MELT Erweiterung (MELT ist eine domänenspezifische High-Level-Sprache, um GCC zu erweitern), die das tut, was Sie wollen (zB zum Beispiel ein zusätzliches builtin, das den Typ seiner Argumente in einer konstanten Zeichenkette kodiert usw.) , aber das erfordert etwas Arbeit (und ist spezifisch für GCC).
Aber ich verstehe nicht, warum Sie solche barocken Dinge in C machen wollen. Wenn dynamisches Tippen für Sie so wichtig ist, warum benutzen Sie keine dynamisch typisierte Sprache?
Tags und Links c++ c++11 forwarding templates-deduction