tuple是类似pair的模板。每个pair的成员类型都不相同,但每个pair都恰好有两个成员。不同tuple类型的成员类型也不相同,但一个tuple可以有任意数量的成员。每个确定的tuple类型的成员数目是固定的,但一个tuple类型的成员数目可以与另一个tuple类型不同。
当我们希望将一些数据组合成单一对象,但又不想麻烦地定义一个新数据结构来表示些数据时,tuple是非常有用的。下面列出了tuple支持的操作。tuple类型及其相关类型和函数都定义在tuple头文件中。
tuple<T1, T2, …, Tn> t; t是一个tuple,成员数为n,第i个成员的类型为Ti。所有成员都进行值初始化。
tuple<T1, T2, …, Tn> t(vl, V2, …, Vn) t是一个tuple,成员类型为Tl..Tn,每个成员用对应的初始值vi进行初始化。此构造函数是explicit的。
make_tuple (v1, v2, …, vn) 返回一个用给定初始值初始化的tuple。tuple的类型从初始值的类型推断。
t1 == t2 或t1 != t2 当两个tuple具有相同数量的成员且成员对应相等时,两个tuple相等。这两个操作使用成员的==运算符来完成。一旦发现某对成员不等,接下来的成员就不用比较了。
t1 relop t2 tuple的关系运算使用字典序两个tuple必须具有相同数量的成员。使用<运算符比较t1的成员和t2中的对应成员
get<i>(t) 返回t的第i个数据成员的引用:如果七是一个左值,结果是一个左值引用:否则,结果是一个右值引用。tuple的所有成员都是public的。
tuple_size<tupleType>::value 一个类模板,可以通过一个tuple类型来初始化。它有一个名为value的publicconstexpr static数据成员,类型为size_t,表示给定tuple类型中成员的数量。
tuple_element<i, tupleType>::type 一个类模板,可以通过一个整型常量和一个tuple类型 来初始化。它有一个名为type的public成员,表示给定tuple类型中指定成员的类型。
当我们定义一个tuple时,需要指出每个成员的类型:
tuple<size_t, size_t, size_t> threeD; // 三个成员都设置为0
tuple<string, vector<double>, int, list<int>> someVal("constants", {3.14, 2.718}, 42, { 0,1,2,3,4,5});
当我们创建一个tuple对象时,可以使用tuple的默认构造函数,它会对每个成员进行值初始化;也可以像本例中初始化someVal -样,为每个成员提供一个初始值。tuple的这个构造函数是explicit的,因此我们必须使用直接初始化语法:
tuple<size_t, size_t, size_t> threeD = {1, 2, 3}; // 错误
tuple<size_t, size_t, size_t> threeD{1, 2, 3}; // 正确
类似make_pair函数,标准库定义了make_tuple函数,我们可以用它来生成tuple对象:
//表示书店交易记录的tuple,包含:ISBN、数量和每册书的价格
auto item = make_tuple(¨0-999-78345-X¨, 3, 20. 00);
类似make_pair,make_tuple函数使用初始值的类型来推断tuple的类型。在本例中,item是一个tuple,类型为tuple<const char*, int, double>。
一个pair总是有两个成员,标准库就可以为它们命名(如,first和second)。但这种命名方式对tuple是不可能的,因为一个tuple类型的成员数目是没有限制的。因此,tuple的成员都是未命名的。要访问一个tuple的成员,就要使用一个名为get的标准库函数模板。为了使用get,我们必须指定一个显式模板实参,它指出我们想要访问第几个成员。我们传递给get 一个tuple对象,它返回指定成员的引用:
auto book = get<0>(item); // 返回item的第一个成员
auto cnt = get<1>(item); // 返回item的第二个成员
auto price = get<2> (item); // 返回item的最后一个成员
get<2>(item) *= 0.8; // 打折20%
尖括号中的值必须是一个整型常量表达式,从0开始。
如果不知道一个tuple准确的类型细节信息,可以用两个辅助类模板来查询tuple成员的数量和类型:
typedefdecltype(item) trans; // trans是item的类型
// 返回trans类型对象中成员的数量
size_t sz = tuple_size<trans>::value; // 返回3
// cnt的类型与item中第二个成员相同
tuple_element(1,trans>::type cnt = get<1>(item); // cnt是一个int
为了使用tuple_size或tuple_element,我们需要知道一个tuple对象的类型。与往常一样,确定一个对象的类型的最简单方法就是使用decltype。在本例中,我们使用decltype来为item类型定义一个类型别名,用它来实例化两个模板。tuple_size有一个名为value的publicstatic数据成员,它表示给定tuple中成员的数量。tuple_element模板除了一个tuple类型外,还接受一个索引值。它有一个名为type的public类型成员,表示给定tuple类型中指定成员的类型。类似get,tuple_element所使用的索引也是从0开始计数的。
关系和相等运算符
tuple的关系和相等运算符的行为类似容器的对应操作。这些运算符逐对比较左侧tuple和右侧tuple的成员。只有两个tuple具有相同数量的成员时,我们才可以比较它们。而且,为了使用tuple的相等或不等运算符,对每对成员使用==运算符必须都是合法的;为了使用关系运算符,对每对成员使用<必须都是合法的。
由于tuple定义了<和==运算符,我们可以将tuple序列传递给算法,并且可以在无序容器中将tuple作为关键字类型。
tuple的一个常见用途是从一个函数返回多个值。