C++ Hana:如何从变量创建类型的元组?
如果我有一个变体,比如:C++ Hana:如何从变量创建类型的元组?,c++,template-meta-programming,boost-hana,C++,Template Meta Programming,Boost Hana,如果我有一个变体,比如: using my_variant = boost::variant<int, bool, std::string>; 使用my_variant=boost::variant; 有没有一种简单的方法可以将变量可以包含的类型提取到Boost.Hana元组中,以便满足以下条件: using boost::hana::type; static_assert(std::is_same<my_tuple, boost::hana::tuple<type&
using my_variant = boost::variant<int, bool, std::string>;
使用my_variant=boost::variant;
有没有一种简单的方法可以将变量可以包含的类型提取到Boost.Hana元组中,以便满足以下条件:
using boost::hana::type;
static_assert(std::is_same<my_tuple, boost::hana::tuple<type<int>, type<bool>, type<std::string>>>{});
使用boost::hana::type;
静态_断言(std::is_same{});
这不使用任何hana功能,但应该可以工作
首先是一个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...>;
};
模板
结构转录;
模板
使用transcribe\u t=typename transcribe::type;
模板
结构转录{
使用类型=Z;
};
现在,一个接受类型并返回hana类型的hana元组的模板:
template<class...Ts>
using tuple_of_types = boost::hana::tuple<boost::hana::type<Ts>...>;
模板
使用tuple\u of_types=boost::hana::tuple;
我们做到了:
template<class Src>
using get_types_from = transcribe_t< tuple_of_types, Src >;
using result = get_types_from< my_variant >;
模板
使用get_types_from=transcribe_t;
使用结果=从获取_type_;
get\u types\u from
是因为提取任意模板的模板参数的类型函数似乎很有用。很久以前,对于这种转换,我遇到过类似的情况。但无法找到这个想法的实际来源,或者这可能是一种非常普遍的做法:
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;
模板结构转换\u impl;
模板
结构转换\u impl
{
使用转换的_type=To;
};
模板
使用convert=typename convert\u impl::converted\u type;
因为我不确定BoostHANA元组,所以我将展示一个std::tuple示例
convert<boost::variant<int, bool, string>, std::tuple>
转换
以下内容将用于开发
(自):
#包括
#包括
#包括
#包括
名称空间hana=boost::hana;
使用my_variant=boost::variant;
constexpr auto my_tuple=hana::to(my_variant::types{});
//注:
//一般来说,不要使用std::is_same来比较hana::tuple;在中使用==
//因为如果元组包含hana::basic_类型,它也可以工作。
静态断言(my_tuple==hana::tuple\u t,“”);
添加了对mpl::list
的支持;以前只支持mpl::vector
,而boost::variant::types
是一个mpl::list
。这就是为什么我的回答需要一段时间;我正在实现那个:-)
编辑
我没有解释为什么我使用constexpr auto my\u tuple=…
而不是使用my\u tuple=decltype(…)
。原因很简单,因为知道my_tuple
的类型不是很有用,因为你不能依赖它。事实上,如果您查看hana::type
的文档,就会发现您不能依赖hana::type
作为任何特定的内容。这有很好的理由,但从可用性的角度来看,这意味着您也不能依赖于hana::tuple
的类型。在进行类型级计算时,与类型级编码相比,更喜欢值级编码(因此auto my_tuple=…
)。这是Hana相对于MPL&friends的特殊性,你应该尽可能地坚持下去,否则你会发现Hana真的很笨重(因为没有考虑到这一点)。只是为了澄清;您想要hana::tuple
,还是hana::tuple
。换句话说,您想要一个类型的元组,还是一个包含类型为variant的对象的元组?一个类型的元组。编辑问题:)虽然可以做一些普通的事情,但是alameta::as_list
会很好(有吗?在文档中看不到)没有,现在没有。然而,我已经思考了一段时间,但我从未真正找到一个令人满意的名字:。但是,我们将能够使用以下事实:boost::variant::types
是一个MPL序列。我正在写我的答案。如果你需要这个功能的任意模板,让我们讨论一下。我同意这会很有用,但我只需要一点说服力和一些帮助来命名这样的功能。这太棒了,谢谢!尽管通用类型列表的解决方案会认为对将hana集成到任何现有的代码库/库中非常有帮助,但我突然想到,使用基于通用专门化的解决方案时应该小心。实际上,一些库组件使用可变模板的模拟,而xxx
则是xxx
。我刚刚检查过,如果编译器支持的话,boost::variant
会使用真正的变量模板,所以现在就可以工作了。但在一般情况下,我们仍必须保持谨慎。
#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>, "");