If I have a variant, like so:
using my_variant = boost::variant<int, bool, std::string>;
Is there an easy way to extract the types the variant can contain into a Boost.Hana tuple so that the following holds:
using boost::hana::type;
static_assert(std::is_same<my_tuple, boost::hana::tuple<type<int>, type<bool>, type<std::string>>>{});
The following will work on develop (since e13d826):
#include <boost/hana.hpp>
#include <boost/hana/ext/boost/mpl.hpp>
#include <boost/variant.hpp>
#include <string>
namespace hana = boost::hana;
using my_variant = boost::variant<int, bool, std::string>;
constexpr auto my_tuple = hana::to<hana::tuple_tag>(my_variant::types{});
// Note:
// In general, don't use std::is_same to compare hana::tuple; use == in
// because it will also work if the tuple contains hana::basic_types.
static_assert(my_tuple == hana::tuple_t<int, bool, std::string>, "");
What e13d826 did was add support for mpl::list; only mpl::vector was supported before, and boost::variant<>::types is a mpl::list. This is why my answer took a while to come; I was implementing that :-).
Edit
I did not explain why I'm using constexpr auto my_tuple = ... instead of using my_tuple = decltype(...). Well, the reason is simply because knowing the type of my_tuple is not really useful, since you can't rely on it. Indeed, if you look at the documentation of hana::type, it's written that you can't rely on hana::type<T> being anything specific. There are good reasons for this, but from a usability point of view it means that you can't rely on the type of hana::tuple<hana::type<...>, ...> being anything specific either. When doing type-level computations, prefer value-level encoding (thus auto my_tuple = ...) to type-level encoding. This is the specificity of Hana over MPL & friends, and you should try to stick with it as much as possible, or you'll find Hana to be really clunky (because not written with that in mind).
This doesn't use any hana features, but should work.
First, a transcribe type function that takes a template, and an instance of a different template, and transcribes the types in the second into the first:
template<template<class...>class To, class From>
struct transcribe;
template<template<class...>class To, class From>
using transcribe_t=typename transcribe<To,From>::type;
template<template<class...>class Z, template<class...>class Src, class...Ts>
struct transcribe<Z, Src<Ts...>> {
using type=Z<Ts...>;
};
Now, a template that takes types, and returns a hana tuple of hana types:
template<class...Ts>
using tuple_of_types = boost::hana::tuple<boost::hana::type<Ts>...>;
And we are done:
template<class Src>
using get_types_from = transcribe_t< tuple_of_types, Src >;
using result = get_types_from< my_variant >;
get_types_from is because a type function that extracts the template arguments of an arbitrary template seems useful.
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