3

例如,我有一个像

std::tuple<T0, T1, T2> tp;

我可以通过函数来​​获取它的元素,std::get()比如

auto e0 = std::get<0>(tp);

我更喜欢使用有意义的索引来访问数字以外的元素。一种方法是定义一个枚举

enum MyEnum
{
    WHAT_T0_MEANS = 0,
    WHAT_T1_MEANS = 1,
    WHAT_T2_MEANS = 2
};

因此我可以使用友好版本的 get like

auto e0 = std::get<WHAT_T0_MEANS>(tp);

问题是有时我发现元组中类型的顺序不友好,将其更改为 like std::tuple<T1, T0, T2>。但是很容易忘记更改枚举中元素的顺序。一个好方法可能是在类 T0 中定义 T0 的含义或使用 map 来查找 T0 的含义,或者。然后写一些函数来通过T0的意思来获取元素。有什么办法吗?这里 T0 的含义不是枚举元素所必需的。它可以是一种类型或其他任何东西。

如果 T0、T1 和 T2 是不同的类型。像这样的功能

T MyGet<T>(tp)

其中 T 可以是 T0、T1 或 T2,都可以。

4

2 回答 2

6

正在进行讨论:

现在,您可以使用带有 Fusion Map 之类的标记元素:

#include <boost/fusion/include/map.hpp>
#include <boost/fusion/include/at_key.hpp>
using namespace boost::fusion;

typedef map<
   pair<struct what_t1_means, int>
 , pair<struct what_t2_means, int> >
map_type;

int main()
{
    map_type m { 42, -42 };

    auto i1 = at_key<what_t1_means>(m);
    auto i2 = at_key<what_t2_means>(m);
}

我选择使用int两次,以强调“键类型”与“元组”类型是分开的。

在http://liveworkspace.org/code/4CxV4T$0上现场观看

于 2013-04-07T01:03:34.430 回答
3
#include <type_traits>
#include <cstddef>
#include <tuple>
using std::size_t;
/*

构建单个type_list. 然后构建tuplefrom said type_list,并得到类似的索引。

基本元编程样板:

*/    
template<typename... Ts>
struct type_list {};
template<typename T, typename list, typename=void>
struct index_of;
template<typename T, typename T0, typename...Ts>
struct index_of<T, type_list<T0, Ts...>, typename std::enable_if<
  std::is_same<T, T0>::value
>::type>: std::integral_constant< size_t, 0 >{};
template<typename T, typename T0, typename...Ts>
struct index_of<T, type_list<T0, Ts...>, typename std::enable_if<
  !std::is_same<T, T0>::value
>::type>: std::integral_constant< size_t, index_of<T, type_list<Ts...>>::value+1 >{};

template<template<typename...>class target, typename source>
struct copy_types;
template<template<typename...>class target, template<typename...>class src, typename... Ts>
struct copy_types<target, src<Ts...>> {
  typedef target<Ts...> type;
};
template<template<typename...>class target, typename source>
using CopyTypes = typename copy_types<target, source>::type;
/*

现在我们创建一个类型列表,并使用它来定义我们的元组和一个get函数:

*/
typedef type_list<int, double, char> my_types;
typedef CopyTypes< std::tuple, my_types > my_tuple;
template<typename T>
T& get_type( my_tuple& t ) {
  return std::get< index_of<T, my_types>::value >(t);
}
template<typename T>
T const& get_type( my_tuple const& t ) {
  return std::get< index_of<T, my_types>::value >(t);
}
/*

如果我们想要标记类型,我们可以使用boost::mpl,或者像这样快速滚动:

*/
template<typename Tag, typename T>
struct tagged_type {
  typedef Tag tag;
  typedef T type;
};

template< typename tagged_type >
using GetType = typename tagged_type::type;
template< typename tagged_type >
using GetTag = typename tagged_type::tag;

template< template<typename...> class target, typename tagged_list >
struct copy_tagged_types;

template< template<typename...> class target, typename... tagged_Ts >
struct copy_tagged_types< target, type_list<tagged_Ts...> >:
  copy_types< target, type_list< GetType<tagged_Ts>... > >
{};

template< template<typename...> class target, typename tagged_list >
using CopyTaggedTypes = typename copy_tagged_types< target, tagged_list >::type;

template< typename Tag, typename tagged_list >
struct get_tag_index;

template< typename Tag, typename...Tagged_Ts >
struct get_tag_index< Tag, type_list< Tagged_Ts...> >:
  index_of< Tag, type_list< GetTag<Tagged_Ts>... > > {};
/*

现在我们有了标记模板元编程库的基础知识。

使用将类似于:

*/
typedef type_list<
  tagged_type<struct bob, int>,
  tagged_type<struct alice, int>
> my_tagged_types;

typedef CopyTaggedTypes< std::tuple, my_tagged_types > my_tuple2;

template<typename Tag>
auto get_tag( my_tuple2& tup )
  ->decltype(std::get< get_tag_index< Tag, my_tagged_types >::value >( tup ))
{
  return std::get< get_tag_index< Tag, my_tagged_types >::value >( tup );
}
template<typename Tag>
auto get_tag( my_tuple2 const& tup )
  ->decltype(std::get< get_tag_index< Tag, my_tagged_types >::value >( tup ))
{
  return std::get< get_tag_index< Tag, my_tagged_types >::value >( tup );
}
/*

这基本上是“自己动手boost::mpl”的情况。:)这里的例子

*/
int main() {
   my_tuple t1;
   get_type<char>(t1) = 'a'; 
   my_tuple2 t2;
   get_tag<bob>(t2) = 7;
}
于 2013-04-07T04:04:40.617 回答