c ++ variadischer Vorlagenkonstruktor und allgemeine Konstruktoren

8

Code wie (c ++ 14):

%Vor%

Der einfache Konstruktor wird aufgerufen, wenn er exakt die gleiche Signatur wie der übergebene Parameter hat. Gibt es einen Trick, um gewöhnliche Konstruktoren wie gewohnt mit einem variadischen Template-Konstruktor zu verwenden, ohne Klassen zu kopieren, als Parameter übergeben und Konstruktoren überladen wie:

%Vor%

Und ohne zusätzliche Tags in Konstruktoren

    
Роман Коптев 05.10.2015, 21:01
quelle

3 Antworten

6

Erstellen Sie zwei Ebenen des Konstruktors. Dann tag Versand.

%Vor%

Die "bevorzugten" ctors haben das Präfix std::true_type , die "weniger bevorzugten" ctors haben das Präfix std::false_type .

Dies hat die üblichen Unvollkommenheiten der perfekten Weiterleitung. Wenn Sie Initialisierungslisten verwenden, möchten Sie vielleicht eine andere "öffentliche" ctor haben, die das explizit übernimmt. Und Funktion Name Argument magical Überladung wird nicht funktionieren. NULL ist ein int . Etc.

Sie können sich eine Version vorstellen, die statt zwei Ebenen eine beliebige Nummer hat. Die is_constructible< ... > -Klausel im Public-Facing-Code wird stattdessen durch eine Magie ersetzt, die den höchsten N findet, so dass tag<N>, blah... das Objekt konstruieren kann (oder den niedrigsten N , je nachdem, wie Sie es machen wollen). Dann gibt es den Typ tag<N> zurück, der dann an diese Ebene versendet.

Verwenden Sie eine Technik wie folgt:

%Vor%

läuft auf ein ernstes Problem weiter, da wir is_constructible in einem Kontext instanziiert haben, in dem es bekommt die Antwort falsch . Und in der Praxis cachen Compiler die Ergebnisse von Template-Instanziierungen, so dass nun das Ergebnis von is_constructible abhängig von der Compiler-Reihenfolge ist (ODR-Verletzung vermute ich).

    
Yakk 09.10.2015, 14:49
quelle
4

Sie können Ihren Variadic-Konstruktor nur dann aktivieren, wenn diese Argumente es nicht erlauben, C auf andere Weise zu erstellen, indem Sie std::is_constructible .

Das ist:

%Vor%

Mit dieser Änderung ruft C c1{s} (2) auf und C c2{"abc", 3} ruft (1) auf, während C c7{1, 2, 3, 4, 5} (4) aufruft.

    
Barry 05.10.2015 21:15
quelle
0

Dies ist eine andere Lösung, die keine Tag-Verteilung verwendet. Hier werden Konstruktoren in der gewählten Reihenfolge getestet, und es kann ein einfacher Konstruktor mit variablem Template verwendet werden, ohne dass eine perfekte Weiterleitung von dem Konstruktor des variadischen Template-Interfaces erfolgt. Z.B. Ich kann Konstruktor mit dem Parameter std :: pair verwenden und darin die Klammerinitialisierungsliste { "String", 6 } , nicht explizit pass std::pair<char const*, size_t>("String", 6) usw. verwenden, wie im Beispiel gezeigt. Diese Methode kann nicht nur verwendet werden, um die Priorität der Konstruktoren zu steuern, sondern auch, um die Priorität der Überladung anderer Elemente zu steuern. Es braucht im Moment eine Helferklasse.

Ich bin neu in verschiedenen Metaprogrammierungstricks, es ist nur ein Vorschlag. Ich werde es nicht verbessern.

%Vor%

Einige standard-ähnliche Klassen:

%Vor%

Klassendefinition zum Beispiel:

%Vor%

Verwenden Sie als:

%Vor%

Programmausgabe:

%Vor%     
Роман Коптев 09.10.2015 22:40
quelle