1. 程式人生 > >C++Primer_Chap17_標準庫特殊設施_List01_tuple型別_筆記

C++Primer_Chap17_標準庫特殊設施_List01_tuple型別_筆記

  tuple是類似pair的模板。不同tuple型別的成員型別可以不同,但一個tuple可以有任一數量的成員。每個確定的tuple型別的成員數目是固定的。但一個tuple型別的成員數目可以與另一個tuple型別不同。

  當我們希望將一些資料組合成單一物件,但又不想麻煩地定義一個新資料結構來表示這些資料時,tuple是非常有用的:

#include <tuple>
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 
t2
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;
    }
}