Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Hana:如何从变量创建类型的元组?_C++_Template Meta Programming_Boost Hana - Fatal编程技术网

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的对象的元组?一个类型的元组。编辑问题:)虽然可以做一些普通的事情,但是ala
meta::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>, "");