3

如果我有一个变体,像这样:

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

3 回答 3

8

以下将起作用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;的支持。onlympl::vector以前受支持,并且boost::variant<>::typesmpl::list. 这就是为什么我的回答需要一段时间才出现的原因;我正在实施:-)。

编辑

我没有解释为什么我使用constexpr auto my_tuple = ...而不是using my_tuple = decltype(...). 好吧,原因很简单,因为知道类型my_tuple并没有真正的用处,因为你不能依赖它。确实,如果您查看 的文档hana::type,就会发现您不能依赖于hana::type<T>任何特定的东西。这有充分的理由,但从可用性的角度来看,这意味着您也不能依赖于hana::tuple<hana::type<...>, ...>任何特定的类型。在进行类型级计算时,更喜欢值级编码(因此auto my_tuple = ...)而不是类型级编码。这是 Hana 相对于 MPL 和朋友的特殊性,你应该尽可能地坚持下去,否则你会发现 Hana 真的很笨重(因为没有考虑到这一点)。

于 2015-11-12T19:37:54.610 回答
2

这不使用任何 hana 功能,但应该可以工作。

首先,一个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 类型的 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是因为提取任意模板的模板参数的类型函数似乎很有用。

于 2015-11-12T19:06:42.060 回答
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;

因为,我不确定 boost hana tuple,所以我将展示一个带有 std::tuple 的示例

convert<boost::variant<int, bool, string>, std::tuple>
于 2015-11-12T19:09:03.117 回答