std::tuple<size_t, size_t, size_t> threeD; //使用默認構造函數
std::tuple<std::string, std::vector<double>, int, std::list<int>>
someVal("constants", { 3.14,2.718 }, 42, { 0,1,2,3,4,5 });
string s;
tuple<string&> t(s);
get<0>(t) = "hello"; //s變為hello
Tuple和初值列template<typename... Args>
void foo(const std::tuple<Args...> t);
int main()
{
foo(42); //錯誤,禁止隱式轉換
foo(make_tuple(42)); //正確
return 0;
}
std::tuple<size_t, size_t, size_t> threeD1 = { 1,2,3 }; //錯誤,不能進行隱式類型轉換了
std::tuple<size_t, size_t, size_t> threeD2{ 1,2,3 }; //正確
std::vector<std::tuple<int, float>> v{ { 1,1,0 },{2,2,0} }; //錯誤
std::tuple<int, int, int> foo() { //錯誤
return{ 1,2,3 };
}
auto item = std::make_tuple("0-999-78345-X", 3, 20.00);
//item類型為tuple<const char*, int, double>
四、訪問tuple成員get()函數auto item = std::make_tuple("0-999-78345-X", 3, 20.00);
auto book = std::get<0>(item); //返回item第一個成員
auto cnt = std::get<1>(item); //返回item第二個成員
auto price = std::get<2>(item) / cnt; //返回最後一個成員,並將其除以cnt
std::get<2>(item) *= 0.8; //打折20%(get返回的是item的引用)
std::tuple<int,double> t1;
get<0>(t1); //正確
int i;
get<i>(t1); //錯誤,運行期才傳入一個索引值
get<3>(t1); //錯誤,索引錯誤,t1隻有兩個元素
tuple_size類模板、tuple_element類模板、tuple_cat類模板//item的類型為tuple<const char*, int, double>
auto item = std::make_tuple("0-999-78345-X", 3, 20.00);
//trans為item的數據類型
typedef decltype(item) trans;
//返回item中的數據成員數量
size_t sz = std::tuple_size<trans>::value;
//type為int
std::tuple_element<1, trans>::type cnt = get<1>(item);
int n;
//tt的類型為tuple<int,double,std::string,int>
auto tt = std::tuple_cat(std::make_tuple(42, 7.7, "hello"), std::tie(n));
五、關係和相等運算符下面是STL容器的比較規則:
如果兩個容器具有相同大小且所有元素都兩兩對應相等,則兩容器相等;否則不相等
如果兩個容器大小不相同,但較小容器中每個元素都等於較大容器中對應元素,則較小容器小於較大容器
如果兩個容器都不是另一個容器的前綴子序列,則它們的比較結果取決於第一個不相等元素的比較結果
tuple與STL容器的比較規則類似,但是:
只有兩個tuple具有相同數量的成員時才可以進行比較
為了使用相等或不等運算符,對每對成員相等或不等運算符都必須是合法的
類似的為了使用關係運算符,對每對成員使用關係運算符也必須是合法的
例如:
std::tuple<std::string, std::string> duo("1", "2");
std::tuple<size_t, size_t> twoD(1, 2);bool b = (duo == twoD);
std::tuple<size_t, size_t, size_t> threeD(1, 2, 3);b = (twoD < threeD);
std::tuple<size_t, size_t> origin(0, 0);b = (origin > twoD); 六、make_tuple()函數、tie()函數make_tuple()//三個元素的類型是int、int、const char*
make_tuple(22, 44, "nico");
//其實第三個元素的類型為const char[5]。當使用type trait std::decay()時,第三個元素的類型衰退為const char*
std::string s;
auto x = std::make_tuple(s); //以s的非引用創建一個tuple
std::get<0>(x) = "my value"; //未改變s的值
auto y = make_tuple(ref(s)); //以s的引用創建一個tuple
std::get<0>(y) = "my value"; //改變s的值
tie()std::tuple<int, float, std::string> t(77, 1.1, "more light");
int i;
float f;
std::string s;
std::tie(i, f, s) = t;
//將t賦值給一個tuple對象(tie()創建返回的tuple),其中都使用i,f,s的引用來創建
//因此,創建之後,i=77,f=1.1,s="more light"
std::tuple<int, float, std::string> t(77, 1.1, "more light");
int i;
std::string s;
//使用t創建一個tuple,tuple的類型為tuple<int,std::string>,其中忽略了t的第二個元素
std::tie(i, std::ignore, s) = t;
七、tuple的輸入/輸出八、使用tuple返回多個值#include <iostream>#include <ostream>#include <sstream>#include <fstream>#include <string>#include <iterator>#include <vector>#include <tuple>#include <algorithm>#include <numeric>using namespace std;
struct Sales_data {std::string isbn()const { return bookNo; }Sales_data(const string& s) :bookNo(s), units_sold(0), revenue(0) {}
Sales_data &operator+=(const Sales_data &rhs) {units_sold += rhs.units_sold;revenue += rhs.revenue;return *this;}
std::string bookNo;unsigned units_sold = 0;double revenue = 0.0;};
ostream &operator<<(ostream &os, const Sales_data &item){os << item.isbn() << " " << item.units_sold << " " << item.revenue << ;return os;}
Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs) {Sales_data sum = lhs;sum += rhs;return sum;}/*
vector<Sales_data>代表一家書店的銷售情況
vector<vector>代表所有書店
*/
vector<vector<Sales_data>> files;
編寫一個返回tuple的函數:
在指定的迭代器區間內尋找參數3所指定的元素
該算法默認使用<運算符來比較,因為Sales_data沒有<運算符,因此我們傳遞給它一個名為compareIsbn函數的指針
該算法返回一個pair,表示元素的範圍。如果未找到,則兩個迭代器相等,表示空範圍
下面我們編寫一個函數,對於一本給定的書,在files中搜索出售過這本書的書店
對每家有銷售記錄的,返回一個tuple類型,保存這家書店的索引和兩個迭代器(索引指出書店在files中的位置,迭代器分別標記書籍在此書店的vector<Sales_data>中第一條銷售記錄和最後一條銷售記錄之後的位置)
equal_range算法:
bool compareIsbn(const Sales_data& lhs, const Sales_data& rhs){return lhs.isbn() < rhs.isbn();}
vector<vector<Sales_data>> files;
typedef tuple<vector<Sales_data>::size_type,vector<Sales_data>::const_iterator,vector<Sales_data>::const_iterator> matches;
vector<matches> 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(std::make_tuple(it - files.cbegin(), found.first, found.second));}
return ret;}使用函數返回tuple:
while循環從in中讀取名為s的書籍,然後調用上面的findBook函數來查找是否有名為s的書籍
如果沒有,則findBook返回的vector為空,那麼使用continue繼續循環
如果查找到了,使用for循環遍歷trans的vector,其中每個元素都是一個tuple
然後使用get得到tuple中的0、1、2三種元素並列印
其中使用了accumulate算法(由於我們定義了Sales_data的加法運算符,因此可以使用這個算法)。accumulate以參數3為初始值,其中使用Sales_data的參數為string的構造函數來構造。又由於我們定義了Sales_data的<<運算符,因此可以輸出到ostream中
void reportResults(istream &in, ostream &os, const vector<vector<Sales_data>> &files){std::string s;
while (in >> s){auto trans = findBook(files, s);
if (trans.empty()) {std::cout << s << "not found in any stores" << std::endl;continue;}else {for (const auto &store : trans) {os << "store: " << std::get<0>(store) << std::endl;os << "sales: " << std::accumulate(std::get<1>(store), std::get<2>(store), Sales_data(s)) << std::endl;}}}}九、自定義列印tuple
演示案例:
#include "printtuple.hpp"#include <tuple>#include <iostream>#include <string>using namespace std;int main(){ tuple <int,float ,string> t(77,1.1, "more light"); cout<< "io: " <<t << endl;}