tuple元组是一个固定大小的不同类型值的集合,是泛化的std::pair。和C#中的tuple类似,但是比C#中的tuple强大得多。我们也可以把它当作一个通用的结构体来用,不需要创建结构体又获取结构体的特征,在某些情况下可以取代结构体,使程序更简洁、直观。
tuple看似简单,其实它是简约而不简单,可以说它是C++11中一个既简单又复杂的类型,简单的一面是它很容易使用,复杂的一面是它内部隐藏了太多细节,往往要和模板元的一些技巧结合起来使用。下面看看tuple的基本用法。
先构造一个tuple: tuple<constchar*, int>tp = make_tuple(sendPack,nSendSize); // 构造一个tuple 这个tuple等价于一个结构体: struct A { char* p; int len; };
用tuple<const char*, int>tp就可以不用创建这个结构体了,而作用是一样的,是不是更简洁直观了?还有一种方法也可以创建元组,用std::tie,它会创建一个元组的左值引用。
auto tp = return std::tie(1, "aa", 2); // tp的类型实际是:std::tuple<int&,string&, int&> 再看看如何获取元组的值: constchar* data = tp.get<0>(); // 获取第一个值 int len = tp.get<1>(); // 获取第二个值 还有一种方法也可以获取元组的值,通过std::tie解包tuple。 int x,y; string a; std::tie(x,a,y) = tp;
通过tie解包后,tp中3个值会自动赋值给3个变量。解包时,如果只想解某个位置的值时,可以用std::ignore占位符来表示不解某个位置的值。比如我们只想解第3个值:
std::tie(std::ignore,std::ignore,y) = tp; // 只解第3个值了 还有一个创建右值的引用元组方法:forward_as_tuple。 std::map<int, std::string> m; m.emplace(std::forward_as_tuple(10, std::string(20, 'a'))); 它实际上创建了一个类似于std::tuple<int&&, std::string&&>类型的tuple。 我们还可以通过tuple_cat连接多个tupe,代码如下: int main() { std::tuple<int, std::string, float> t1(10, "Test", 3.14); int n = 7; auto t2 = std::tuple_cat(t1, std::make_pair("Foo", "bar"), t1, std::tie(n)); n = 10; print(t2); } 输出结果如下: (10, Test, 3.14, Foo, bar, 10, Test, 3.14, 10)
可以看到tuple的基本用法还是比较简单的,也很容易使用。然而tuple是简约而不简单,它有很多高级的用法,具体内容将在第2章中介绍。
tuple虽然可以用来代替简单的结构体,但不要滥用,如果用tuple来替代3个以上字段的结构体时就不太合适了,因为使用tuple可能会导致代码的易读性降低,如果到处都是std::get<N>(tuple),反而不直观,建议对于多个字段的结构体时,不要使用tuple。