Якщо у мене є варіант, то так:
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>>>{});
Відповіді:
5 за відповідь № 1Наступне буде працювати 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 та друзями, і ви повинні намагатися дотримуватися її якомога більше, або ви побачите, що Хана дійсно незграбна (тому що не написано з урахуванням цього).
2 для відповіді № 2
Це не використовує будь-які функції hana, але повинно працювати.
По-перше, a transcribe
тип, який приймає шаблон, і екземпляр іншого шаблону, і переносить типи у другій:
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 tuple типів 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 для відповіді № 3
Якийсь час назад я натрапив на щось подібне до цього для такої конверсії. Не вдається знайти дійсне джерело цієї ідеї, або це може бути навіть досить загальноприйнятою практикою:
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;
Оскільки, я не впевнений, що посилення hana tuple, я покажу приклад зі std :: tuple
convert<boost::variant<int, bool, string>, std::tuple>