Es gibt mehr als eine Möglichkeit, dies zu tun. Sie müssen sie nicht alle verstehen, sondern nur einen mit den gewünschten Funktionen finden.
Hier sind drei sehr unterschiedliche Möglichkeiten, dies zu tun.
Transkribieren von einer Instanz zu einer Vorlage
template<class Src, template<class...>class Dest>
struct transcribe;
template<class Src, template<class...>class Dest>
using transcribe_t=typename transcribe<Src,Dest>::type;
template<template<class...>class Src, class...Ts, template<class...>class Dest>
struct transcribe<Src<Ts...>, Dest>{
using type=Dest<Ts...>;
};
dann:
transcribe_t<decltype(topics), Foo> x;
intrusiv von Foo Modifizieren
Dies kann auch intrusiv durch Foo
Modifizierung getan werden, um ein Bündel zu nehmen statt eine Packung.
template <class Bundle>
struct Foo;
template <typename... T>
struct Foo<PossibleTypes<T...>>{
std::tuple<T...> member;
};
oder
template <template<class...>class Z, typename... T>
struct Foo<Z<T...>>{
std::tuple<T...> member;
};
dann:
Foo<decltype(topics)> x;
, die viel praktischer sein kann, wenn Sie gerade nicht in einem Satz von ...
Argumente zu übergeben.
Wertorientiertes metaprogramming
Wir können auch diese mit wertorientierten Ansatz metaprogramming:
template<class T>
struct tag_t {constexpr tag_t(){} using type=T;};
template<class T>
constexpr tag_t<T> tag{};
template<template<class...>class Z>
struct ztemplate_t {
constexpr ztemplate_t() {}
template<class...Ts> using apply=Z<Ts...>;
template<class...Ts>
constexpr tag_t<Z<Ts...>> operator()(tag_t<Ts>...)const{ return {}; }
};
template<template<class...>class Z>
constexpr ztemplate_t<Z> ztemplate{};
template<class Tag>
using type=typename Tag::type;
template <class... T>
struct PossibleTypes {
template<template<class...>class Z>
constexpr auto operator()(ztemplate_t<Z> z) const {
return z(tag<T>...);
}
};
geben Sie uns:
int main(){
type<decltype(topics(ztemplate<Foo>)) > x;
return 0;
}
, die ziemlich glatt ist. Live example.
tag
hebt einen Typ in einen Wert auf. ztemplate
hebt eine Vorlage in einen Wert auf.
ztemplate<some_template>(tag<T0>, tag<T1>)
gibt eine tag
des Ergebnisses der some_template
-T0, T1
wie tag_t<some_template<T0, T1>>
Anwendung.
Um von einem Tag zu einem Typ zurückzukehren, machen wir einen type<decltype(some_tag_expression)>
.
Ich habe Ihre PossibleTypes
geändert, um auch eine operator()(ztemplate)
zu haben, die die Vorlage auf die in PossibleTypes
gespeicherten Typen anwendet.
Diese Art von Wahnsinn funktioniert besser, da Sie mehr und mehr typbasierte Manipulation vornehmen, da die wertebasierte Programmierung in C++ viel aussagekräftiger und einfacher zu verwenden ist als die Vorlagensyntax.
@mihai Keiner der oben genannten erfordert das Objekt instanziieren? In jedem Fall erstelle ich den Typ. Dann, weil Ihr Code das getan hat, erstelle ich eine Instanz des Typs (um zu beweisen, dass es funktioniert hat, denke ich). Entfernen Sie dann 'x' und Sie haben einen Typ Ausdruck und keine Instanz. Verwenden Sie typedef oder verwenden Sie, um ihm einen Namen oder was auch immer zu geben. – Yakk
Arf leid. Problem in einem anderen Teil des Codes. Funktioniert super! –