Если у меня есть вариант, вот так:
using my_variant = boost::variant<int, bool, std::string>;
Есть ли простой способ извлечь типы, которые вариант может содержать в кортеже Boost.Hana, так что выполняется следующее:
using boost::hana::type;
static_assert(std::is_same<my_tuple, boost::hana::tuple<type<int>, type<bool>, type<std::string>>>{});
Следующее будет работать на develop
(поскольку 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>, "");
Какие e13d826 сделал добавить поддержку mpl::list
; только mpl::vector
был поддержан ранее, и boost::variant<>::types
это mpl::list
, Вот почему мой ответ занял некоторое время; Я реализовывал это :-).
редактировать
Я не объяснил, почему я использую constexpr auto my_tuple = ...
вместо using my_tuple = decltype(...)
, Ну, причина в том, что зная тип my_tuple
не очень полезно, так как вы не можете полагаться на это. Действительно, если вы посмотрите на документацию hana::type
написано, что на тебя нельзя положиться hana::type<T>
быть чем-то конкретным. Для этого есть веские причины, но с точки зрения удобства использования это означает, что вы не можете полагаться на тип hana::tuple<hana::type<...>, ...>
быть чем-то конкретным либо. При выполнении вычислений на уровне типов предпочитайте кодирование на уровне значений (таким образом, auto my_tuple = ...
) для кодирования на уровне типа. Это специфика хана над MPL & друзья, и вы должны стараться придерживаться этого как можно больше, или вы обнаружите, что Хана очень неуклюжа (потому что не написана с учетом этого).
Это не использует никаких функций хана, но должно работать.
Первый transcribe
Функция type, которая принимает шаблон и экземпляр другого шаблона и транскрибирует типы из второго в первый:
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...>;
};
Теперь шаблон, который принимает типы и возвращает кортеж hana с типами hana:
template<class...Ts>
using tuple_of_types = boost::hana::tuple<boost::hana::type<Ts>...>;
И мы сделали:
template<class Src>
using get_types_from = transcribe_t< tuple_of_types, Src >;
using result = get_types_from< my_variant >;
get_types_from
потому что функция типа, которая извлекает аргументы шаблона произвольного шаблона, кажется полезной.
Некоторое время назад я столкнулся с чем-то похожим на это для такого обращения. Не удалось найти фактический источник этой идеи, или это может быть даже довольно распространенная практика:
template<class From, template<class...> class To> struct convert_impl;
template<template<class...> class From, class... Types,
template<class...> class To>
struct convert_impl<From<Types...>, To>
{
using converted_type = To<Types...>;
};
template<class From, template<class...> class To>
using convert = typename convert_impl<From, To>::converted_type;
Поскольку я не уверен насчет бустерного хана, я покажу пример с std :: tuple
convert<boost::variant<int, bool, string>, std::tuple>