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

时间:2017-02-20 15:09:04

标签: c++ c++11

我们假设我有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>>;

如何实现?

修改

使用boost :: tuple或vector和transform可以更轻松吗?可以转换应用于元级别吗?

3 个答案:

答案 0 :(得分:0)

您可以使用部分专业化:

template<typename TypesTuple>
struct Bar;

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

因此my_bar.queue的类型为std::tuple<std::priority_queue<int>, std::priority_queue<double>>

Live demo

答案 1 :(得分:0)

另一种方式:

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

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

但是,只有在元组包含1到3个元素且它们满足std::priority_queue模板参数要求时才有效,例如:

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

答案 2 :(得分:0)

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

这是一个类型的类型和类型映射的类型,并在您通过映射映射所包含的类型后返回类型。

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

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

template_map_t可以通过多种方式完成。

虽然我不建议,但这是一种hana风格:

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

这些是constexpr值,分别存储类型和模板。

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

zapply现在允许我们使用值将模板应用于类型。

我们现在可以写一个地图功能:

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

并提取类型:

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

带有测试代码:

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 ) >;

显示类型图有效。

Live example