C++Primer_Chap17_標準庫特殊設施_List01_tuple型別_筆記
阿新 • • 發佈:2018-11-11
tuple是類似pair的模板。不同tuple型別的成員型別可以不同,但一個tuple可以有任一數量的成員。每個確定的tuple型別的成員數目是固定的。但一個tuple型別的成員數目可以與另一個tuple型別不同。
當我們希望將一些資料組合成單一物件,但又不想麻煩地定義一個新資料結構來表示這些資料時,tuple是非常有用的:
#include <tuple>
tuple<T1, T2, ..., Tn> t; | t是一個tuple,成員數為n,第i個成員的型別是Ti。所有成員都進行值初始化 |
tuple<T1, T2, ..., Tn> t(v1, v2, ..., vn); | 使用初始值vi進行初始化。此建構函式是explicit的(只能直接初始化) |
make_tuple(v1, v2, ..., vn) | 返回一個用給定初始值初始化的tuple。tuple的型別從初始值的型別推斷 |
t1 == t2 t1 != t2 |
當兩個tuple具有相同數量的成員且成員對應相等時,兩個tuple相等。一旦發現某對成員不等,接下來成員不再比較 |
t1 relop |
tuple的關係運算使用字典序。兩個tuple必須具有相同數量的成員。使用<運算子比較成員 |
get<i>(t) | 返回t的第i個數據成員的引用:如果t是一個左值,返回左值引用;否則返回右值引用。 tuple的所有成員都是public的 |
tuple_size<tupleType>::value | 一個類模板,可以通過一個tuple型別來初始化。它有一個名為value的public constexpr static資料成員,型別為size_t,表示給定tuple型別中的成員數目 |
tuple_element<i, tupleType>::type | 一個類模板,可以通過一個整型常量和一個tuple型別來初始化。它有一個名為type的public成員,表示給定tuple型別中知道成員的型別 |
定義和初始化tuple
由於建構函式是explicit的,所以定義時不能拷貝構造。
#include <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});
tuple<size_t, size_t, size_t> threeD = {1, 2, 3}; //錯誤:explicit
tuple<size_t, size_t, size_t> threeD{1, 2, 3};
auto item = make_tuple{"0-999-78345-X", 3, 20.00};
decltype(item) = tuple<const char*, int ,double>
auto book = get<0>(item);
auto cnt = get<1>(item);
auto price = get<2>(item) / cnt;
get<2>(item) *= 0.8;
typedef decltype(item) trans;
size_t sz = tuple_size<trans>::value;
tuple_element<1, trans>::type cnt = get<1>(item);
tuple的關係和相等運算子的行為類似容器的對應操作。這些運算子逐對比較成員。為了支援關係和相等比較,每對元素使用運算子必須是合法的。
使用tuple返回多個值
tuple的一個常見用途是從一個函式返回多個值。
typedef tuple< vector<Sales_data>::size_type,
vector<Sales_data>::const_iterator,
vector<Sales_data>::const_iterator> matcher;
vector<matcher>
findBook( const vector<vector<Sales_data>> &files,
const string &book)
{
vector<matches> ret;
for(auto it = files.cbegin(); it != files.cend(); ++it)
{
auto found = equal_range(it->cbegin(), it->cend(),
book, compareIsbn);
if( found.first != found.second)
ret.push_back(make_tuple(it - files.cbegin(),
found.first, found.second));
}
return ret;
}
void reportResults(istream &in, ostream &os,
const vector<vector<Sales_data>> &files)
{
string s;
while( in >> s)
{
auto trans = findBook(files, s);
if( trans.empty())
{
cout << s << " not found in any stores" << endl;
continue;
}
for(const auto &store : trans)
os << "store" << get<0>(store) << " sales:"
<< accumulate(get<1>(store), get<2>(store), Sales_data(s));
<< endl;
}
}