Хана: Как мне создать кортеж типов из варианта?

Если у меня есть вариант, вот так:

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>>>{});

3

Решение

Следующее будет работать на 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 & друзья, и вы должны стараться придерживаться этого как можно больше, или вы обнаружите, что Хана очень неуклюжа (потому что не написана с учетом этого).

7

Другие решения

Это не использует никаких функций хана, но должно работать.

Первый 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 потому что функция типа, которая извлекает аргументы шаблона произвольного шаблона, кажется полезной.

2

Некоторое время назад я столкнулся с чем-то похожим на это для такого обращения. Не удалось найти фактический источник этой идеи, или это может быть даже довольно распространенная практика:

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>
2
По вопросам рекламы [email protected]