In the following C++14 code, I would like to create a container of PossibleTypes using variadic templates. Next, I would like to create another container with a member tuple of the types previously specified.
How would one go about in doing so? I would like to have Foo contain a tuple of < int, double >, just as the templated types of topics.
Many thanks in advance.
#include <iostream>
#include <tuple>
#include <type_traits>
template <typename... T>
struct PossibleTypes {};
PossibleTypes<int,double> topics;
template <typename... T>
struct Foo{
std::tuple<T...> member;
};
int main(){
Foo<??(topics)??> x;
return 0;
}
There is more than one way to do this. You don't have to understand them all, just find one that has the features you want.
Here are three very different ways to do this.
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...>;
};
then:
transcribe_t<decltype(topics), Foo> x;
This can also be done intrusively by modifying Foo to take a bundle instead of a pack.
template <class Bundle>
struct Foo;
template <typename... T>
struct Foo<PossibleTypes<T...>>{
std::tuple<T...> member;
};
or
template <template<class...>class Z, typename... T>
struct Foo<Z<T...>>{
std::tuple<T...> member;
};
then:
Foo<decltype(topics)> x;
which can be much more practical if you aren't just passing in one set of ... arguments.
We can also approach this using value-based 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>...);
}
};
giving us:
int main(){
type<decltype( topics(ztemplate<Foo>) ) > x;
return 0;
}
which is pretty slick. Live example.
tag lifts a type into a value. ztemplate lifts a template into a value.
ztemplate<some_template>( tag<T0>, tag<T1> ) returns a tag of the result of applying some_template to T0, T1 like tag_t<some_template<T0, T1>>.
To move back to a type from a tag, we do a type<decltype(some_tag_expression)>.
I modified your PossibleTypes to also have an operator()(ztemplate) that applies the template to the types stored in PossibleTypes.
This kind of insanity works better as you do more and more type based manipulation, as value-based programming in C++ is much more expressive and easier to work with than the template syntax.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With