To be honest I don't know how to start to search the solution for the problem I try to solve. Probably a solution already is. So the task is here.
I have a class that actually is template with 2 arguments:
template <typename F, typename S>
class trans {...};
also I have another class that holds a chain of these "trans" classes like a tuple (example):
class holder {
using chain_type = std::tuple<trans<std::string, int>,
trans<int, float>,
trans<float, std::string>,
trans<std::string, json>>;
};
And as can be seen every second argument of a "trans" is the same as the next first. The chain:
std::string -> int -> float -> std::string -> json.
what would I want...I'd like to have some method to make this chain like this:
template <typename ...Args>
class holder {
using chain_type = trans_chain_create_t<Args...>;
};
holder<std::string, int, float, std::string, json> h;
Is it possible? I'm not very familiar with variadic templates and use them very rare.
Yes, it is possible:
template< typename F, typename S >
class trans {};
template< typename F, typename S, typename... Tail >
struct create_trans_chain;
template< typename F, typename S, typename... Tail >
using create_trans_chain_t = typename create_trans_chain< F, S, Tail... >::type;
template< typename F, typename S >
struct create_trans_chain< F, S >
{
using type = std::tuple< trans< F, S > >;
};
template< typename F, typename S, typename Next, typename... Tail >
struct create_trans_chain< F, S, Next, Tail... >
{
using type = decltype(std::tuple_cat(
std::declval< create_trans_chain_t< F, S > >(),
std::declval< create_trans_chain_t< S, Next, Tail... > >()));
};
With Boost.Mp11, this is pretty short (as always):
template <typename ...Args>
using trans_chain_create_t =
mp_transform<trans,
mp_pop_back<std::tuple<Args...>>,
mp_pop_front<std::tuple<Args...>>>;
mp_transform
is basically a zip
, we're zipping (Args
without the tail) with (Args
without the head) and then pairwise applying trans
to that.
You can split the above by adding a helper metafunction, zip_tail
:
template <template <typename...> class F, typename L>
using zip_tail = mp_transform<F, mp_pop_back<L>, mp_pop_front<L>>;
template <typename ...Args>
using trans_chain_create_t = zip_tail<trans, std::tuple<Args...>>;
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