2016-07-29 22 views
4

Ich versuche Vorlagen in C++ zu verwenden, Folgendes zu tun:eine Art Austausch innerhalb eines Tupels in C++ 11

Ich habe eine Funktion wie folgt aus:

template<typename... Args> 
void f1(const std::tuple<Args...>& t1); 

Innerhalb dieser Funktion Ich möchte ein weiteres Tupel t2 so erstellen, dass jedes Element von t1 an derselben Stelle in t2 kopiert wird, außer für Elemente des Typs A, für die t2 ein Objekt vom Typ B erzeugen soll. Der Konstruktor von .2 B bezieht sich auf ein Objekt vom Typ Asowie ein zweites Argument vom Typ C&. Eine Instanz von C wird vor der Konvertierung erstellt und sollte als zweites Argument an den Konstruktor B übergeben werden, wenn ein Objekt vom Typ A gefunden wird.

Etwas Ähnliches, nur völlig verallgemeinert:

std::tuple<int, B, double, B> Convert(std::tuple<int, A, double, A> tpl, C& c) 
{ 
    return std::tuple<int, B, double, B>(
    std::get<0>(tpl), 
    B(std::get<1>(tpl), c), 
    std::get<2>(tpl), 
    B(std::get<3>(tpl), c), 
); 
} 
+2

Okay, mit welchem ​​Problem haben Sie konfrontiert? SO ist kein kostenloser Outsourcing-Standort. –

+0

Ich ging nicht sehr weit; an anderen Stellen meines Codes musste ich Vorlagencode schreiben, der Tupel manipuliert, wie zum Beispiel das Anwenden einer Funktion, die eine Reihe von Argumenten auf ein Tupel mit Feldern derselben Typen wie die Argumente verwendet (das Gegenteil tun, also eine Reihe von Argumente in ein Tupel, ist einfach), also versuche ich immer einen Weg zu finden, ob ich ein Tupel t1 bekomme oder dass ich eine Reihe von Argumenten habe, aber ich gehe nirgendwohin ... – sunmat

+0

Wenn dieses dumme 'C &' Ding nicht da wäre, wäre das ein relativ einfaches Stück Metaprogrammierung (vorausgesetzt, Sie haben natürlich Zugriff auf C++ 14). Aber da diese Einschränkung vorhanden ist, wird es wahnsinnig schwierig, da die Ausdrücke, die Sie verwenden, um jeden Wert zu konstruieren, nun * verschieden * sind, abhängig vom Typ dieses Wertes. Sie müssen einen Weg finden, um den Ausdruck zu normalisieren, was erfordert, ein 'Tuple'-in-einem-' Tuple' oder etwas zu erzeugen. –

Antwort

3

Hinweis: Die neue Frage bittet um etwas komplexer. Lassen Sie diese Antwort für diejenigen, die davon profitieren könnten.

Die Macht der Vorlage conditionals und Vorlagenpaket Erweiterung:

template<typename... Args> 
void f1(const std::tuple<Args...>& t1) { 
    std::tuple<typename std::conditional< 
     std::is_same<A, Args>::value, B, Args>::type...> t2(t1); 
    // Both Args are expanded in parallel, resulting in the same types 
    // Do things with t2 
} 
+0

Danke, das ist ein Anfang, aber ich habe vergessen zu erwähnen, dass der Konstruktor von B ein const A & und ein anderes Argument nimmt; Wie kann ich das 2. Argument an den Konstruktor übergeben? – sunmat

+0

Ich habe meine Frage bearbeitet. Vielen Dank. – sunmat

+0

@sunmat: Das ist eine andere und komplexere Frage. Kann aber trotzdem gemacht werden. – Deduplicator

1

Ich denke, das das Problem lösen würde:

#include<functional> 
#include<tuple> 
#include<cassert> 

struct A {}; 
struct C {}; 
struct B { B(const A &, C &) {} }; 

template<typename T> 
T g(const T &t, C &) { return t; } 

B g(const A &a, C &c) { 
    return B{a, c}; 
} 

template<std::size_t... I, typename... Args> 
void f(const std::tuple<Args...> &tup,std::index_sequence<I...>) { 
    C c; 
    auto val = std::make_tuple(g(std::get<I>(tup), c)...); 
    assert((std::is_same<std::tuple<C, B, C>, decltype(val)>::value)); 
} 

template<typename... Args> 
void f(const std::tuple<Args...> &tup) { 
    f(tup, std::make_index_sequence<sizeof...(Args)>()); 
} 

int main() { 
    auto tup = std::make_tuple(C{}, A{}, C{}); 
    f(tup); 
} 

Beachten Sie, dass diese Lösung C++ 14 erfordert, vor allem wegen der std::make_index_sequence und std::index_sequence.
Sie können bei Bedarf eine geeignete C++ 11-Implementierung von ihnen online finden.

+0

Sie können die Zuordnung in einer separaten Funktion isolieren, die einfach durch 'f' mit der richtigen Zuordnung (definiert in einer lokalen Klasse) aufgerufen wird. – Deduplicator

+0

@Deduplicator Ja, das ist ein minimales, funktionierendes Beispiel. Ich weiß nicht, wie ich den Code strukturieren soll, denn ich weiß nicht, was das wahre Weltpron ist. – skypjack