/ / Mehrere Template-Klasse in einen Template-Template-Parameter werfen - Template-Bindung? - C ++, Vorlagen, Vorlagenvorlagen

Multiple-Template-Klasse in einen Template-Template-Parameter werfen - Template-Bindung? - C ++, Vorlagen, Vorlagen-Vorlagen

In der folgenden Klasse gegeben:

template <class T, template <typename> class B>
class A { B<T> b; };

Ich kann jetzt Code wie diesen schreiben:

A<float, MyVector> a1;
A<int, MySet> a2;

Was ist der eleganteste Weg, Multi-Parameter-Klassen, von denen alle Parameter außer einem angegeben werden, in B zu setzen? Wie eine Karte mit Int-Tasten? Das einzige, was ich mir vorstellen kann, ist folgendes:

template <class U> using C = MyMap<int, U>;
A<float, C<int>> a3;

Gibt es eine solche Vorlage, die der von std entspricht:bind, wo können wir nur einen Teil der Parameter angeben und einen davon offen lassen? Ich bin mir ziemlich sicher, dass die Sprache dies nicht vorsieht, aber die Leute müssen das schon gelöst haben.

A<float, MyMap<int, _>> a3;

Antworten:

4 für die Antwort № 1

Es gibt keine eingebaute Vorlage, die äquivalent ist zu std::bind, aber Sie können selbst schreiben. Hier ist eine einfache Version, die das erste Vorlagenargument bindet, das Sie an Ihre Bedürfnisse anpassen können:

template <typename T, template <typename...> class B>
struct bind_t1 {
template <typename... Ts>
using type = B<T,Ts...>;
};

Dann benutzt du einfach bind_t1 so:

A<float, bind_t1<int, std::map>::type> a3;

Beachten Sie, dass Sie für Ihr Beispiel Ihre Vorlagenparameter ändern müssen, um eine variadische Vorlagenvorlage zu erstellen:

template <class T, template <typename...> class B>
class A { B<T> b; };

Hier ist eine etwas erweiterte Version, die am Anfang der Parameterliste eine Anzahl zusammenhängender Elemente binden kann:

template <template <typename...> class B, typename... Ts>
struct bind_nt1 {
template <typename... Us>
using type = B<Ts...,Us...>;
};

//Usage
A<std::less<int>, bind_nt1<std::map, int, float>::type> a3;

Hier ist eine generische Version, die auf dem Weg basiert std::bind macht Dinge Es führt keine Validierung durch und hat wahrscheinlich einige Randfälle, aber es ist ein guter Ausgangspunkt. Dank an Piotr Skotnicki für Verbesserungen.

template <std::size_t N>
struct placeholder{};

template <template <typename...> class B, typename... Ts>
struct bind_t {
private:
template <typename T, typename UTuple>
struct resolve_placeholder {
using type = T;
};

template <std::size_t N, typename UTuple>
struct resolve_placeholder<placeholder<N>, UTuple> {
using type = typename std::tuple_element<N-1, UTuple>::type;
};

public:
template <typename... Us>
using type = B<typename resolve_placeholder<Ts, std::tuple<Us...>>::type...>;
};


//Usage
A<int, bind_t<std::map, float, placeholder<1>, std::less<float>>::type> a3;

Auf diese Weise können Sie sogar die Reihenfolge der Vorlagenparameter ändern:

//std::map<int,float>
bind_t<std::map, placeholder<2>, placeholder<1>>::type<float, int> b;