技术: C++11 tuple 容器

以前说变参模板(valiadic templates)的时候说过, tuple就是借助变参模板的实现的; 现在主要说说其用法及一些常用代码.

主要用途如下, 直接贴代码了:

1
2
3
4
5
6
7
8
9
//create tuple with make_tuple()
auto t2 = make_tuple(22, 44, "sss");

//std::get<>() 模板, 避免一个个head, tail方法的使用
tuple<int, float, string> t1(2, 3.3 "string");
cout << "t:" << get<0>(t1) << '' << get<1>(t1) << '' << get<0>(t2) << endl;

//赋值
get<0>(t2) = get<1>(t1);

打印 tuple 元素

cout << t2; 这个不行, 需要你自己去设计实现一个<<方法, 利用valiadic template, 例如参考实现:(参考boost的代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template<typename...Args>
ostream& operator<<(ostream& os, const tuple<Args...> &t)
{
os << "[";
PRINT_TUPLE<0, sizeof...(Args), Args...>::print(os, t);
return os<<"]";
}

//最后一次特化&调用, 前两个模板参数相同的情况的特化版本
//所以只写 int MAX
template<int MAX, typename...Args>
struct PRINT_TUPLE<MAX, MAX, Args...>
{
static void print(std::ostream& os, const tuple<Args...>&t){//do nothing}
};

template<int IDX, int MAX, typename...Args>
struct PRINT_TUPLE
{
static void print(ostream& os, const tuple<Args...> &t)
{
os << get<IDX>(t) << (IDX+1==MAX ? "":",");
PRINT_TUPLE<IDX+1, MAX, Args...>::print(os,t); //最后一次IDX+1=MAX调用特化版本
}
};

tuple的大小tuple_size

1
2
3
//处理类型属于元编程的范畴 (一般编程都是对变量, 对象做操作)
typedef tuple<int, float, string> T;
cout << tuple_size<T>::value << endl; //3, 其实是问类型的个数

tuple元素的类型tuple_element

1
2
//拿到(元素)类型
tuple_element<1, T>::type f ;

《Modern C++ Design》中再没有设计tuple的时候(设计层级对象的继承体系), 是怎么做的呢?

1
2
3
//产生层级继承体系
typedef GenScatterHiderarchy<TYPELIST_4(int, int, string, widget), Holder> Foo;
Foo aFoo;

此时aFoo对象图就是(int, int, string, Widget),

TYPELIST_4的实现, 他们用的是宏定义, 一系列宏定义

1
2
3
4
5
#define TYPELIST_1(T1) Typelist<T1, NullType>
#define TYPELIST_2(T1, T2) Typelist<T1, TYPELIST_1(T2)>
#define TYPELIST_3(T1, T2, T3) Typelist<T1, TYPELIST_2(T2, T3)>
#define TYPELIST_4(T1, T2, T3) Typelist<T1, Typelist_3(T2, T3, T4)>
//...

可以看到和tuple思想类似, 用的是head+tail的方法. (早起版本的boost tuple也是这么做的, 手动宏定义实现的)

|