/ / Hana: Як створити кортеж типів з варіанту? - c + +, шаблон-мета-програмування, boost-hana

Хана: Як створити групу типів з варіанту? - c + +, шаблон-мета-програмування, boost-hana

Якщо у мене є варіант, то так:

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

Наступне буде працювати develope13d826):

#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>