Das obige Zitat aus dem Standardentwurf spricht über das, was Teil der Grammatik in den Links beschrieben ist das „Muster“, das erweitert wird. Um es zu verstehen, müssen Sie wissen, wie die C++ - Grammatik beschrieben ist, und die Ausnahmen, wie sie im Standardtext selbst verwendet werden; Wenn Sie jedoch grundlegendes BNF-Wissen und ein wenig Geduld haben, können Sie es erarbeiten. Die Namen sind oft auch nützlich.
Sie können jedoch ...
verwenden und vor allem verstehen es fast so tief, ohne dabei.
Die allgemeine Regel ist einfach: Sie etwas wenig C++ Grammatik (die so genannten Muster) auf die übliche Art und Weise analysiert, wobei ein Satz von Typen wie eine einzige Art behandelt wird, und eine Packung von Literalen ist behandelt wie ein einzelnes Literal. Dann, am Ende davon, haben Sie einen ... Expander.Es nimmt dann alle unexpanded Packs in das Bit der C++ - Grammatik unmittelbar vor (das Muster) und erweitert es.
Wie dies in jedem Kontext funktioniert, ist anders; es ist nicht nur eine Makroerweiterung. Die Kontexte, in denen ...
gültig ist, sind oben aufgezählt; Die Auswirkungen der Erweiterung sind im Standard an jedem Punkt aufgeführt, an dem sie gültig sind.
In den banalsten Anwendungsfällen von ...
, ist das Muster ein Ausdruck, und der Ausdruck erweitert wird als-ob es jeweils durch ,
getrennt Kopie (nicht operator,
, aber die anderen „normale“ ein), in der Regel in einem Kontext, in dem eine Liste von Dingen erwartet wird (Funktionsaufruf, Initialisierungsliste usw.).
Es gibt Funktionsparameter Deklaration Kontexten (wo ...
sowohl die Typen der Funktionsparameter erweitert und stellt eine neue Packung der Paramter Namen), in Template-Parameter-Listen (wo es in der Regel eine Packung einführt) usw.
sizeof...
ist ein bisschen seltsam: für sizeof...
zählt, wie viele Elemente in der Packung in der ()
übergeben werden. Dies funktioniert anders, da sich die ...
nicht auf die "Struktur auf der linken Seite" bezieht.
Für alignas(X...)
beenden wir mit alignas([email protected]), alignas([email protected]), ...
oben (wo @0
mein Pseudo-Code für das erste Element des Pakets ist), als alignas([email protected], [email protected], ...)
nicht gültig C++ (wieder @ T. C. In den Kommentaren unten).
Für die Vererbung wird eine Reihe von Basisklassen erstellt. Für mem-initializer-lists können Sie ctor-Argumente an das Paket von Basisklassen übergeben. Für lambdas gibt es eine begrenzte Erfassung von Packs (nicht voll bei Ausdruckserfassung mit der zuletzt von mir überprüften Erweiterung).
Das Muster ist die Sache erweitert. Wichtig ist, dass ein erweitertes Muster nicht durch einen anderen Musterexpander erweitert wird: so ist std::array< Ts, sizeof...(Ts) >...
ein Paket von Arrays verschiedener Typen, jedes mit einer Anzahl von Elementen, die dadurch bestimmt wird, wie groß das Paket selbst ist. sizeof...(Ts)
"zählt als Erweiterung" die Ts
in seiner ()
, obwohl ...
ist nicht "richtig", weil die Sprache definiert Ts
in der ()
als das Muster, das durch die ...
erweitert wird.
Das Muster im allgemeinen Fall kann nicht als Ausdruck bezeichnet werden, da Typen keine Ausdrücke sind und einige Muster Ausdrücke sind (oder zumindest in Listen von Ausdrücken auftauchen). Und in einigen Fällen erweitert ...
ein type-pattern in ein erweitertes Paket von Typen (wie im throw-Ausdruck).
Die allgemeine Regel, dass Sie ...
als Erweiterung das Ding auf der linken Seite in geeigneter Weise im lokalen Kontext behandeln, arbeitet für fast alles außer sizeof...
(was ein magischer Operator ist, dass Sie, wie viele Elemente in einem Parameter erzählt Pack). Es wird nur in Eckfällen sein, wo dies kein anständiges Modell hervorbringt. Und nach meiner Erfahrung wird es im schlimmsten Fall zu Code führen, der nicht kompiliert, wenn Sie denken, dass er es sollte; In diesem Fall können Sie Workarounds lernen. Denken Sie daran, dass eine nackte Aussage "keinen lokalen Kontext hat", so dass Sie nicht die (void)(int[]){0,(a = std::get<Is>(tup)),0)...};
(möglicherweise int[]
) tun müssen, wo wir einen Kontext (Erstellen eines Arrays) für die Pack-Erweiterung zur Verfügung stellen .
C++ 1z Falte Ausdrücke sind eine andere schrullige Stelle, wo ...
gilt nicht auf der linken Seite; hier wollten sie eine Erweiterung eines binären Operators haben, so dass "links" nicht so viel Sinn macht wie die übliche "unäre" Erweiterung.
[Dies] (http://en.cppreference.com/w/cpp/language/parameter_pack) hat nicht geholfen? – NathanOliver
@NathanOliver, nein, diese cppreference.com-Seite ist eine von vielen, die sich auf Muster bezieht, ohne jemals zu definieren, was ein Muster ist. – Alan
http://eel.is/c++draft/temp.variadic#4 –