简体   繁体   English

将一个std :: tuple映射到另一个std :: tuple

[英]Mapping a std::tuple to another std::tuple

Let's assume I have a std::tuple<Types...> , I want to generate a std::tuple<std::priority_queue<Types...>> 假设我有一个std::tuple<Types...> ,我想生成一个std::tuple<std::priority_queue<Types...>>

#include <queue>
#include <tuple>

template<typename TypesTuple>
struct Bar {
    std::priority_queue<std::for_each_tuple_type(TypesTuple)...> queues;
};

using Foo = Bar<std::tuple<int, double>>;

How can that be achieved? 如何实现?

EDIT 编辑

Could it get easier with boost::tuple or vector and transform? 使用boost :: tuple或vector进行转换会变得更容易吗? Can transform be applied on the meta level? 可以在元级别应用转换吗?

You can use partial specialization: 您可以使用部分专业化:

template<typename TypesTuple>
struct Bar;

template<typename... Ts>
struct Bar<std::tuple<Ts...>> {
    std::tuple<std::priority_queue<Ts>...> queues;
};

So my_bar.queue will be of type std::tuple<std::priority_queue<int>, std::priority_queue<double>> . 因此my_bar.queue的类型将为std::tuple<std::priority_queue<int>, std::priority_queue<double>>

Live demo 现场演示

Another way: 其他方式:

template<class... Types>
std::tuple<std::priority_queue<Types...>> convert(std::tuple<Types...>);

using Foo = decltype(convert(std::declval<std::tuple<int>>());

However, that only works if the tuple contains 1 to 3 elements and they satisfy std::priority_queue template argument requirements, eg: 但是,仅当元组包含1到3个元素并且它们满足std::priority_queue模板参数要求时,该方法才有效,例如:

using Foo = decltype(convert( std::declval<std::tuple<int, std::vector<int>, std::less<int> > >() ));
template<class In, template<class...>class Map>
struct template_map;
template<class In, template<class...>class Map>
using template_map_t=typename template_map<In, Map>::type;

template<template<class...>class Z, class...Ts, template<class...>class Map>
struct template_map<Z<Ts...>, Map> {
  using type=Z<Map<Ts>...>;
};

This takes a type that is a template over types, and a type map, and returns the type after you map the enclosed types by the map. 这将使用一个作为类型之上的模板的类型和一个类型映射,并在通过映射映射包含的类型之后返回该类型。

template<typename TypesTuple>
struct Bar {
  template_map_t<TypesTuple, std::priority_queue> queues;
};

using Foo = Bar<std::tuple<int, double>>;

Writing template_map_t can be done in many ways. 编写template_map_t可以通过多种方式完成。


While I wouldn't advise it, here is a hana-style: 虽然我不建议这样做,但这是一种哈娜风格:

template<class T>struct tag_t{ constexpr tag_t() {}; using type=T; };
template<class T>constexpr tag_t<T> tag{};

template<template<class...>class Z>
struct ztemplate_t{
  constexpr ztemplate_t() {};
  template<class...Ts>using apply=Z<Ts...>;
};
template<template<class...>class Z>
constexpr ztemplate_t<Z> ztemplate{};

These are constexpr values which store types and templates respectively. 这些是constexpr值,分别存储类型和模板。

template<class Z, class...Ts>
constexpr auto zapply( Z, tag_t<Ts>... )
-> tag_t< typename Z::template apply<Ts...> >
{ return {}; }

zapply now lets us use values to apply templates to types. zapply现在允许我们使用值将模板应用于类型。

We can now write a map function: 我们现在可以编写一个map函数:

template<template<class...>class Z, class...Ts, class zM>
constexpr auto zmap( tag_t<Z<Ts...>>, zM )
{ return zapply( ztemplate<Z>, zapply( zM{}, tag<Ts> )... ); }

and extract the type: 并提取类型:

template<class Tag>using type_t=typename Tag::type;

template<typename TypesTuple>
struct Bar {
  using queues_t = type_t<decltype(
    zmap( tag<TypesTuple>, ztemplate<std::priority_queue> )
  )>;
  queues_t queues;
};

with test code: 带有测试代码:

using Foo = Bar<std::tuple<int, double>>;

tag_t< std::tuple< std::priority_queue<int>, std::priority_queue<double> > > test = tag< decltype( std::declval<Foo&>().queues ) >;

which shows the type map worked. 该图显示了类型映射的工作原理。

Live example . 现场例子

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM