2016-07-29 11 views
3

Ich habe gelesen this, this, this und viele andere ... aber keiner dieser Beiträge antwortet oder ist auf mein spezifisches Problem anwendbar.Variadic Vorlage Konstruktor mit mehreren Parametern Packs

Ich habe eine Struktur X mit einem variadische Template-Konstruktor:

struct X 
{ 
    template<typename... T> 
    X(T... t) { /*...*/ } 
}; 

Und ich habe eine Struktur Y die X zwei Objekte vom Typ enthält. Ich möchte eine Vorlage Konstruktor für Y definieren, so dass man richtig, beide Mitglieder des Typs initialisieren X mit unterschiedlichen Parameter-Liste, also etwas, das wie dem folgenden Code aussieht (was natürlich nicht funktioniert):

struct Y 
{ 
    template<typename... U, typename... V> 
    Y(U&&... u, V&&... v)        // this does not work 
     : x1(std::forward(u)...), x2(std::forward(v)...) // this is was I need to do 
     {} 

    X x1, x2; 
}; 

Wie konnte Ich mache das, indem ich Wrapper, Tupel oder irgendeine geeignete Metaprogrammierungsmaschine benutze? Eine C++ 14-Lösung ist akzeptabel.

+0

@ πάντα ῥεῖ: Ich bitte für C++ 14; Die Frage, die du verlinkt hast, ist vielleicht eine passende Lösung für mein Problem, aber es ist 2 Jahre alt! vielleicht gibt es einen besseren mit C++ 14. – shrike

+0

Ich bin nicht so sicher, dass C++ 14 viel über das Entpacken von VTPs geändert hat, aber gut ... –

+0

@ πάντα ῥεῖ: Sie sind sich nicht sicher? Ich bin mir ziemlich sicher, dass C++ 14 ein paar neue interessante Funktionen zum Auspacken von Tupeln hinzugefügt hat ... – shrike

Antwort

1

Bog-Standard index_sequence Trick.

struct Y 
{ 
private: 
    template<typename... U, typename... V, 
      std::size_t... UIs, std::size_t... VIs> 
    Y(std::tuple<U...>&& u, std::tuple<V...>&& v, 
     std::index_sequence<UIs...>, std::index_sequence<VIs...>) 
     : x1(std::get<UIs>(std::move(u))...), 
      x1(std::get<VIs>(std::move(v))...) 
     {} 
public: 
    template<typename... U, typename... V> 
    Y(std::tuple<U...> u, std::tuple<V...> v) 
     : Y(std::move(u), std::move(v), 
      std::index_sequence_for<U...>{}, 
      std::index_sequence_for<V...>{}) 
     {} 

    X x1, x2; 
}; 

In C++ 17, nur verwenden make_from_tuple:

struct Y 
{ 
public: 
    template<typename... U, typename... V> 
    Y(std::tuple<U...> u, std::tuple<V...> v) 
     : x1(std::make_from_tuple<X>(std::move(u))), 
      x2(std::make_from_tuple<X>(std::move(v))) 
     {} 

    X x1, x2; 
}; 
+0

Vielen Dank, Ihr Trick funktioniert gut ... es sei denn, ich möchte Referenzen auf innere Objekte weitergeben 'x1' & 'x2'; (Ich versuchte es mit' std :: forward_as_tuple() ', aber das hat nicht funktioniert.) Gibt es einen Weg dazu Modifizieren Sie Ihren Code so, dass er mit Tupel von Referenzen arbeiten kann? (Ich habe meine Frage aktualisiert, um die perfekte Weiterleitung zu zeigen, die ich brauche.) – shrike

+0

Es sollte keine Änderung erforderlich sein. –

+0

Das stimmt! Ich habe Fehler in der Parameterliste gemacht. Ihr Trick funktioniert auch für Referenzen perfekt. Danke vielmals. – shrike