1. 程式人生 > >C++11中std::tuple的使用

C++11中std::tuple的使用

std::tuple是類似pair的模板。每個pair的成員型別都不相同,但每個pair都恰好有兩個成員。不同std::tuple型別的成員型別也不相同,但一個std::tuple可以有任意數量的成員。每個確定的std::tuple型別的成員數目是固定的,但一個std::tuple型別的成員數目可以與另一個std::tuple型別不同。

但我們希望將一些資料組合成單一物件,但又不想麻煩地定義一個新資料結構來表示這些資料時,std::tuple是非常有用的。我們可以將std::tuple看作一個”快速而隨意”的資料結構。

當我們定義一個std::tuple時,需要指出每個成員的型別。當我們建立一個std::tuple物件時,可以使用tuple的預設建構函式,它會對每個成員進行值初始化;也可以為每個成員提供一個初始值,此時的建構函式是explicit的,因此必須使用直接初始化方法。類似make_pair函式,標準庫定義了make_tuple函式,我們還可以使用它來生成std::tuple物件。類似make_pair,make_tuple函式使用初始值的型別來推斷tuple的型別。

一個std::tuple型別的成員數目是沒有限制的,因此,tuple的成員都是未命名的。要訪問一個tuple的成員,就要使用一個名為get的標準庫函式模板。為了使用get,我們必須指定一個顯式模板實參,它指出我們想要訪問第幾個成員。我們傳遞給get一個tuple物件,它返回指定成員的引用。get尖括號中的值必須是一個整型常量表達式。與往常一樣,我們從0開始計數,意味著get<0>是第一個成員。

為了使用tuple_size或tuple_element,我們需要知道一個tuple物件的型別。與往常一樣,確定一個物件的型別的最簡單方法就是使用decltype。

std::tuple的關係和相等運算子的行為類似容器的對應操作。這些運算子逐對比較左側tuple和右側tuple的成員。只有兩個tuple具有相同數量的成員時,我們才可以比較它們。而且,為了使用tuple的相等或不等運算子,對每對成員使用==運算子必須都是合法的;為了使用關係運算符,對每對成員使用<必須都是合法的。由於tuple定義了<和==運算子,我們可以將tuple序列傳遞給演算法,並且可以在無序容器中將tuple作為關鍵字型別。

std::tuple的一個常見用途是從一個函式返回多個值。

std::tuple是一個模板,允許我們將多個不同型別的成員捆綁成單一物件。每個tuple包含指定數量的成員,但對一個給定的tuple型別,標準庫並未限制我們可以定義的成員數量上限。

std::tuple中元素是被緊密地儲存的(位於連續的記憶體區域),而不是鏈式結構。

std::tuple實現了多元組,這是一個編譯期就確定大小的容器,可以容納不同型別的元素。多元組型別在當前標準庫中被定義為可以用任意數量引數初始化的類模板。每一模板引數確定多元組中一元素的型別。所以,多元組是一個多型別、大小固定的值的集合。

下面是從其他文章中copy的測試程式碼,詳細內容介紹可以參考對應的reference:

#include "tuple.hpp" #include <iostream> #include <tuple> #include <string> #include <functional> #include <utility>   ////////////////////////////////////////////////////////// // reference: http://www.cplusplus.com/reference/tuple/tuple/ int test_tuple_4() { { // tuple::tuple: Constructs a tuple object. This involves individually constructing its elements,   // with an initialization that depends on the constructor form invoke     std::tuple<int, char> first;                             // default     std::tuple<int, char> second(first);                    // copy     std::tuple<int, char> third(std::make_tuple(20, 'b'));   // move     std::tuple<long, char> fourth(third);                   // implicit conversion     std::tuple<int, char> fifth(10, 'a');                    // initialization     std::tuple<int, char> sixth(std::make_pair(30, 'c'));    // from pair / move       std::cout << "sixth contains: " << std::get<0>(sixth);     std::cout << " and " << std::get<1>(sixth) << '\n'; }   { // std::tuple::operator=: Each of the elements in the tuple object is assigned its corresponding element     std::pair<int, char> mypair(0, ' ');       std::tuple<int, char> a(10, 'x');     std::tuple<long, char> b, c;       b = a;                                // copy assignment     c = std::make_tuple(100L, 'Y');       // move assignment     a = c;                                // conversion assignment     c = std::make_tuple(100, 'z');        // conversion / move assignment     a = mypair;                           // from pair assignment     a = std::make_pair(2, 'b');           // form pair /move assignment       std::cout << "c contains: " << std::get<0>(c);     std::cout << " and " << std::get<1>(c) << '\n'; }   { // std::tuple::swap: Exchanges the content of the tuple object by the content of tpl,   // which is another tuple of the same type (containing objects of the same types in the same order)     std::tuple<int, char> a(10, 'x');     std::tuple<int, char> b(20, 'y');       a.swap(b);     std::cout << "a contains: " << std::get<0>(a);     std::cout << " and " << std::get<1>(a) << '\n';       std::swap(a, b);     std::cout << "a contains: " << std::get<0>(a);     std::cout << " and " << std::get<1>(a) << '\n'; }   { // std::relational operators: Performs the appropriate comparison operation between the tuple objects lhs and rhs     std::tuple<int, char> a(10, 'x');     std::tuple<char, char> b(10, 'x');     std::tuple<char, char> c(10, 'y');       if (a == b) std::cout << "a and b are equal\n";     if (b != c) std::cout << "b and c are not equal\n";     if (b<c) std::cout << "b is less than c\n";     if (c>a) std::cout << "c is greater than a\n";     if (a <= c) std::cout << "a is less than or equal to c\n";     if (c >= b) std::cout << "c is greater than or equal to b\n"; }       return 0; }   //////////////////////////////////////////////// // reference: https://msdn.microsoft.com/en-us/library/bb982771.aspx int test_tuple_3() {     typedef std::tuple<int, double, int, double> Mytuple;       Mytuple c0(0, 1, 2, 3);     // display contents " 0 1 2 3"      std::cout << " " << std::get<0>(c0);     std::cout << " " << std::get<1>(c0);     std::cout << " " << std::get<2>(c0);     std::cout << " " << std::get<3>(c0);     std::cout << std::endl;       Mytuple c1;     c1 = c0;     // display contents " 0 1 2 3"      std::cout << " " << std::get<0>(c1);     std::cout << " " << std::get<1>(c1);     std::cout << " " << std::get<2>(c1);     std::cout << " " << std::get<3>(c1);     std::cout << std::endl;       std::tuple<char, int> c2(std::make_pair('x', 4));     // display contents " x 4"      std::cout << " " << std::get<0>(c2);     std::cout << " " << std::get<1>(c2);     std::cout << std::endl;       Mytuple c3(c0);     // display contents " 0 1 2 3"      std::cout << " " << std::get<0>(c3);     std::cout << " " << std::get<1>(c3);     std::cout << " " << std::get<2>(c3);     std::cout << " " << std::get<3>(c3);     std::cout << std::endl;       typedef std::tuple<int, float, int, float> Mytuple2;       Mytuple c4(Mytuple2(4, 5, 6, 7));     // display contents " 4 5 6 7"      std::cout << " " << std::get<0>(c4);     std::cout << " " << std::get<1>(c4);     std::cout << " " << std::get<2>(c4);     std::cout << " " << std::get<3>(c4);     std::cout << std::endl;       return (0); }   /////////////////////////////////////////////////// // reference: http://zh.cppreference.com/w/cpp/utility/tuple static std::tuple<double, char, std::string> get_student(int id) {     if (id == 0) return std::make_tuple(3.8, 'A', "Lisa Simpson");     if (id == 1) return std::make_tuple(2.9, 'C', "Milhouse Van Houten");     if (id == 2) return std::make_tuple(1.7, 'D', "Ralph Wiggum");     throw std::invalid_argument("id"); }   int test_tuple_2() {     auto student0 = get_student(0);     std::cout << "ID: 0, "         << "GPA: " << std::get<0>(student0) << ", "         << "grade: " << std::get<1>(student0) << ", "         << "name: " << std::get<2>(student0) << '\n';       double gpa1;     char grade1;     std::string name1;     std::tie(gpa1, grade1, name1) = get_student(1);     std::cout << "ID: 1, "         << "GPA: " << gpa1 << ", "         << "grade: " << grade1 << ", "         << "name: " << name1 << '\n';       return 0; }   /////////////////////////////////////////////// // reference: http://www.cplusplus.com/reference/tuple/ static void print_pack(std::tuple<std::string&&, int&&> pack) {     std::cout << std::get<0>(pack) << ", " << std::get<1>(pack) << '\n'; }   static void fun(int &a) {     a = 15; }   int test_tuple_1() { { // std::tuple_element: class template, Class designed to access the type of the Ith element in a tuple.   // It is a simple class with a single member type, tuple_element::type,   // defined as an alias of the type of the Ith element in a tuple of type T.     auto mytuple = std::make_tuple(10, 'a');       std::tuple_element<0, decltype(mytuple)>::type first = std::get<0>(mytuple);     std::tuple_element<1, decltype(mytuple)>::type second = std::get<1>(mytuple);       std::cout << "mytuple contains: " << first << " and " << second << '\n'; }   { // std::tuple_size: Class template designed to access the number of elements in a tuple     std::tuple<int, char, double> mytuple(10, 'a', 3.14);       std::cout << "mytuple has ";     std::cout << std::tuple_size<decltype(mytuple)>::value;     std::cout << " elements." << '\n'; }   { // std::forward_as_tuple: function template, Constructs a tuple object with rvalue references   // to the elements in args suitable to be forwarded as argument to a function.     std::string str("John");     print_pack(std::forward_as_tuple(str + " Smith", 25));     print_pack(std::forward_as_tuple(str + " Daniels", 22)); }   { // std::get: funtion template, Returns a reference to the Ith element of tuple tpl.     std::tuple<int, char> mytuple(10, 'a');       std::get<0>(mytuple) = 20;       std::cout << "mytuple contains: ";     std::cout << std::get<0>(mytuple) << " and " << std::get<1>(mytuple);     std::cout << std::endl; }   { // std::make_tuple: function template, Constructs an object of the appropriate tuple type   // to contain the elements specified in args     auto first = std::make_tuple(10, 'a');             // tuple < int, char >       const int a = 0; int b[3];                         // decayed types:     auto second = std::make_tuple(a, b);               // tuple < int, int* >       auto third = std::make_tuple(std::ref(a), "abc");  // tuple < const int&, const char* >       std::cout << "third contains: " << std::get<0>(third);     std::cout << " and " << std::get<1>(third);     std::cout << std::endl; }   { // std::tie: function template, Constructs a tuple object whose elements are references   // to the arguments in args, in the same order   // std::ignore: object, This object ignores any value assigned to it. It is designed to be used as an   // argument for tie to indicate that a specific element in a tuple should be ignored.     int myint;     char mychar;       std::tuple<int, float, char> mytuple;       mytuple = std::make_tuple(10, 2.6, 'a');          // packing values into tuple       std::tie(myint, std::ignore, mychar) = mytuple;   // unpacking tuple into variables       std::cout << "myint contains: " << myint << '\n';     std::cout << "mychar contains: " << mychar << '\n'; }   { // std::tuple_cat: function template, Constructs an object of the appropriate tuple type   // to contain a concatenation of the elements of all the tuples in tpls, in the same order     std::tuple<float, std::string> mytuple(3.14, "pi");     std::pair<int, char> mypair(10, 'a');       auto myauto = std::tuple_cat(mytuple, std::tuple<int, char>(mypair));       std::cout << "myauto contains: " << '\n';     std::cout << std::get<0>(myauto) << '\n';     std::cout << std::get<1>(myauto) << '\n';     std::cout << std::get<2>(myauto) << '\n';     std::cout << std::get<3>(myauto) << '\n'; }   { // tuple::tuple: A tuple is an object capable to hold a collection of elements.     // Each element can be of a different type.     std::tuple<int, char> foo(10, 'x');     auto bar = std::make_tuple("test", 3.1, 14, 'y');       std::get<2>(bar) = 100;                                    // access element       int myint; char mychar;       std::tie(myint, mychar) = foo;                            // unpack elements     std::tie(std::ignore, std::ignore, myint, mychar) = bar;  // unpack (with ignore)       mychar = std::get<3>(bar);       std::get<0>(foo) = std::get<2>(bar);     std::get<1>(foo) = mychar;       std::cout << "foo contains: ";     std::cout << std::get<0>(foo) << ' ';     std::cout << std::get<1>(foo) << '\n'; }   {     std::tuple<int, char> foo{ 12, 'a' };     std::cout << std::get<0>(foo) << "\n"; // 12     fun(std::get<0>(foo));     std::cout << std::get<0>(foo) << "\n"; // 15 }       return 0; }

GitHub:https://github.com/fengbingchun/Messy_Test ---------------------  作者:fengbingchun  來源:CSDN  原文:https://blog.csdn.net/fengbingchun/article/details/72835446  版權宣告:本文為博主原創文章,轉載請附上博文連結!