In C ++ 11 gibt es verschiedene Vorlagen wie diese:
template< class T, class... Args >
unique_ptr<T> make_unique( Args&&... args )
{
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
Hier gibt es einige Kuriositäten: Der Ausdruck std::forward<Args>(args)...
verwendet beide Args
und args
nur einen ...
Token. Darüber hinaus std::forward
ist eine nicht variadische Vorlagenfunktion nur ein Vorlagenparameter und ein Argument. Was sind die Syntaxregeln dafür (ungefähr)? Wie kann es verallgemeinert werden?
Außerdem: In der Funktionsimplementierung steht die Ellipse ( ...
) am Ende der Interessenbekundung. Gibt es einen Grund dafür, dass in der Liste der Vorlagenargumente und in der Parameterliste die Auslassungspunkte in der Mitte stehen?
c++
c++11
variadic-templates
Ralph Tandetzky
quelle
quelle
...
kommt das vor der Einführung des Bezeichners. Wenn Sie eine oder beide Arten von Paketen verwenden, wird...
das Ausdrucksmuster nach dem Ausdruck erweitert.Antworten:
Im Zusammenhang mit der variadische schablonen die Auslassungspunkte
...
verwendet , um die Template - Parameter Packung auszupacken , wenn er auf der rechten Seite des Ausdrucks angezeigt (nennen diesen Ausdruck Muster für einen Moment). Die Regel ist, dass jedes Muster auf der linken Seite...
wiederholt wird - die entpackten Muster (nennen sie jetzt Ausdrücke ) werden durch Komma getrennt,
.Dies lässt sich am besten anhand einiger Beispiele verstehen. Angenommen, Sie haben diese Funktionsvorlage:
Wenn ich diese Funktion
T
als Übergabe aufrufe{int, char, short}
, wird jeder Funktionsaufruf wie folgt erweitert:In dem von Ihnen geposteten Code
std::forward
folgt das vierte Muster, das durch einenn()
Funktionsaufruf dargestellt wird.Beachten Sie den Unterschied zwischen
x(args)...
undy(args...)
über!Sie können
...
ein Array auch folgendermaßen initialisieren:was dazu erweitert wird:
Ich habe gerade festgestellt, dass ein Muster sogar Zugriffsspezifizierer enthalten kann
public
, wie im folgenden Beispiel gezeigt:In diesem Beispiel wird das Muster wie folgt erweitert:
Das heißt,
mixture
leitet sich öffentlich von allen Basisklassen ab.Hoffentlich hilft das.
quelle
x+args...
sollte erweitert werdenx+arg0,x+arg1,x+arg2
, nichtx+arg0,arg1,arg2
....
gilt also für jede erweiterbare Entität im Muster.x+args...
sollte erweiternx+arg0,x+arg1,x+arg2
, nichtx+arg0,arg1,arg2
.sizeof...(T)
wird dort nicht benötigt. Sie können einfach schreiben:int a[] = { ___ };
Das Folgende stammt aus dem Vortrag "Variadic Templates are Funadic" von Andrei Alexandrescu auf der GoingNative 2012. Ich kann es für eine gute Einführung in Variadic Templates empfehlen.
Es gibt zwei Dinge, die man mit einem variadic Pack machen kann. Es ist möglich
sizeof...(vs)
, die Anzahl der Elemente zu ermitteln und zu erweitern.Erweiterungsregeln
Die Expansion erfolgt nach innen nach außen. Wenn Sie zwei Listen im Sperrschritt erweitern, müssen sie dieselbe Größe haben.
Mehr Beispiele:
Erweitert alle
Ts
in der Vorlagenargumentliste vonA
und dann wird die Funktionhun
mit allen erweitertvs
.Erweitert alle
Ts
in der Vorlagenargumentliste vonA
und allevs
als Funktionsargumente fürhun
.Erweitert die Funktion
hun
mitTs
undvs
im Sperrschritt.Hinweis:
Ts
ist kein Typ undvs
kein Wert! Sie sind Aliase für eine Liste von Typen / Werten. Jede Liste ist möglicherweise leer. Beide gehorchen nur bestimmten Handlungen. Folgendes ist also nicht möglich:Erweiterungsorte
Funktionsargumente
Initialisierungslisten
Basisspezifizierer
Mitgliederinitialisierungslisten
Tempate Argumentlisten
Wird nur kompiliert, wenn eine mögliche Übereinstimmung für die Argumente vorliegt.
Erfassungslisten
Attributlisten
Es ist in der Spezifikation enthalten, aber es gibt noch kein Attribut, das als Typ ausgedrückt werden kann.
quelle