/ / Hana: come posso creare una tupla di tipi da una variante? - c ++, template-meta-programming, boost-hana

Hana: come faccio a creare una tupla di tipi da una variante? - c ++, template-meta-programming, boost-hana

Se ho una variante, in questo modo:

using my_variant = boost::variant<int, bool, std::string>;

Esiste un modo semplice per estrarre i tipi che la variante può contenere in una tupla Boost.Hana in modo tale che:

using boost::hana::type;
static_assert(std::is_same<my_tuple, boost::hana::tuple<type<int>, type<bool>, type<std::string>>>{});

risposte:

5 per risposta № 1

Quanto segue funzionerà develop (da 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>, "");

Che cosa e13d826 è stato aggiunto il supporto per mpl::list; solo mpl::vector era supportato prima, e boost::variant<>::types è un mpl::list. Questo è il motivo per cui la mia risposta ha richiesto un po 'di tempo a venire; Lo stavo implementando :-).

modificare

Non ho spiegato perché sto usando constexpr auto my_tuple = ... invece di using my_tuple = decltype(...). Bene, la ragione è semplicemente perché conoscendo il tipo di my_tuple non è veramente utile, dal momento che non si può fare affidamento su di esso. Infatti, se si guarda la documentazione di hana::type, è scritto che non puoi fidarti hana::type<T> essere qualcosa di specifico. Ci sono buone ragioni per questo, ma dal punto di vista dell'usabilità significa che non puoi fare affidamento sul tipo di hana::tuple<hana::type<...>, ...> essere qualcosa di specifico sia. Quando esegui calcoli a livello di codice, preferisci la codifica a livello di valore (quindi auto my_tuple = ...) per la codifica a livello di testo. Questa è la specificità di Hana rispetto a MPL e agli amici, e dovresti cercare di seguirla il più possibile, altrimenti troverai Hana molto goffo (perché non è scritto con questo in mente).


2 per risposta № 2

Questo non usa alcuna caratteristica di hana, ma dovrebbe funzionare.

Primo, a transcribe digita la funzione che prende un modello e un'istanza di un modello diverso e trascrive i tipi nel secondo nel primo:

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...>;
};

Ora, un modello che accetta i tipi e restituisce una tupla hana di tipi hana:

template<class...Ts>
using tuple_of_types = boost::hana::tuple<boost::hana::type<Ts>...>;

E abbiamo finito:

template<class Src>
using get_types_from = transcribe_t< tuple_of_types, Src >;

using result = get_types_from< my_variant >;

get_types_from è perché una funzione di tipo che estrae gli argomenti del modello di un modello arbitrario sembra utile.


2 per risposta № 3

Qualche tempo fa mi ero imbattuto in qualcosa di simile a questa conversione. Non è in grado di trovare la vera fonte di questa idea o potrebbe anche essere una pratica abbastanza comune:

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;

Dato che non sono sicuro dell'enormità di haup tuple, mostrerò un esempio con std :: tuple

convert<boost::variant<int, bool, string>, std::tuple>