C++11中std::tuple的使用
std::tuple是類似pair的模板。每個(gè)pair的成員類型都不相同,但每個(gè)pair都恰好有兩個(gè)成員。不同std::tuple類型的成員類型也不相同,但一個(gè)std::tuple可以有任意數(shù)量的成員。每個(gè)確定的std::tuple類型的成員數(shù)目是固定的,但一個(gè)std::tuple類型的成員數(shù)目可以與另一個(gè)std::tuple類型不同。
但我們希望將一些數(shù)據(jù)組合成單一對(duì)象,但又不想麻煩地定義一個(gè)新數(shù)據(jù)結(jié)構(gòu)來(lái)表示這些數(shù)據(jù)時(shí),std::tuple是非常有用的。我們可以將std::tuple看作一個(gè)”快速而隨意”的數(shù)據(jù)結(jié)構(gòu)。
當(dāng)我們定義一個(gè)std::tuple時(shí),需要指出每個(gè)成員的類型。當(dāng)我們創(chuàng)建一個(gè)std::tuple對(duì)象時(shí),可以使用tuple的默認(rèn)構(gòu)造函數(shù),它會(huì)對(duì)每個(gè)成員進(jìn)行值初始化;也可以為每個(gè)成員提供一個(gè)初始值,此時(shí)的構(gòu)造函數(shù)是explicit的,因此必須使用直接初始化方法。類似make_pair函數(shù),標(biāo)準(zhǔn)庫(kù)定義了make_tuple函數(shù),我們還可以使用它來(lái)生成std::tuple對(duì)象。類似make_pair,make_tuple函數(shù)使用初始值的類型來(lái)推斷tuple的類型。
一個(gè)std::tuple類型的成員數(shù)目是沒(méi)有限制的,因此,tuple的成員都是未命名的。要訪問(wèn)一個(gè)tuple的成員,就要使用一個(gè)名為get的標(biāo)準(zhǔn)庫(kù)函數(shù)模板。為了使用get,我們必須指定一個(gè)顯式模板實(shí)參,它指出我們想要訪問(wèn)第幾個(gè)成員。我們傳遞給get一個(gè)tuple對(duì)象,它返回指定成員的引用。get尖括號(hào)中的值必須是一個(gè)整型常量表達(dá)式。與往常一樣,我們從0開(kāi)始計(jì)數(shù),意味著get<0>是第一個(gè)成員。
為了使用tuple_size或tuple_element,我們需要知道一個(gè)tuple對(duì)象的類型。與往常一樣,確定一個(gè)對(duì)象的類型的最簡(jiǎn)單方法就是使用decltype。
std::tuple的關(guān)系和相等運(yùn)算符的行為類似容器的對(duì)應(yīng)操作。這些運(yùn)算符逐對(duì)比較左側(cè)tuple和右側(cè)tuple的成員。只有兩個(gè)tuple具有相同數(shù)量的成員時(shí),我們才可以比較它們。而且,為了使用tuple的相等或不等運(yùn)算符,對(duì)每對(duì)成員使用==運(yùn)算符必須都是合法的;為了使用關(guān)系運(yùn)算符,對(duì)每對(duì)成員使用<必須都是合法的。由于tuple定義了<和==運(yùn)算符,我們可以將tuple序列傳遞給算法,并且可以在無(wú)序容器中將tuple作為關(guān)鍵字類型。
std::tuple的一個(gè)常見(jiàn)用途是從一個(gè)函數(shù)返回多個(gè)值。
std::tuple是一個(gè)模板,允許我們將多個(gè)不同類型的成員捆綁成單一對(duì)象。每個(gè)tuple包含指定數(shù)量的成員,但對(duì)一個(gè)給定的tuple類型,標(biāo)準(zhǔn)庫(kù)并未限制我們可以定義的成員數(shù)量上限。
std::tuple中元素是被緊密地存儲(chǔ)的(位于連續(xù)的內(nèi)存區(qū)域),而不是鏈?zhǔn)浇Y(jié)構(gòu)。
std::tuple實(shí)現(xiàn)了多元組,這是一個(gè)編譯期就確定大小的容器,可以容納不同類型的元素。多元組類型在當(dāng)前標(biāo)準(zhǔn)庫(kù)中被定義為可以用任意數(shù)量參數(shù)初始化的類模板。每一模板參數(shù)確定多元組中一元素的類型。所以,多元組是一個(gè)多類型、大小固定的值的集合。
下面是從其他文章中copy的測(cè)試代碼,詳細(xì)內(nèi)容介紹可以參考對(duì)應(yīng)的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 invokestd::tuple<int, char> first; // defaultstd::tuple<int, char> second(first); // copystd::tuple<int, char> third(std::make_tuple(20, 'b')); // movestd::tuple<long, char> fourth(third); // implicit conversionstd::tuple<int, char> fifth(10, 'a'); // initializationstd::tuple<int, char> sixth(std::make_pair(30, 'c')); // from pair / movestd::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 elementstd::pair<int, char> mypair(0, ' ');std::tuple<int, char> a(10, 'x');std::tuple<long, char> b, c;b = a; // copy assignmentc = std::make_tuple(100L, 'Y'); // move assignmenta = c; // conversion assignmentc = std::make_tuple(100, 'z'); // conversion / move assignmenta = mypair; // from pair assignmenta = std::make_pair(2, 'b'); // form pair /move assignmentstd::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 rhsstd::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 tuplestd::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 argsauto 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 tuplestd::tie(myint, std::ignore, mychar) = mytuple; // unpacking tuple into variablesstd::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 orderstd::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 elementint myint; char mychar;std::tie(myint, mychar) = foo; // unpack elementsstd::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"; // 12fun(std::get<0>(foo));std::cout << std::get<0>(foo) << "\n"; // 15
}return 0;
}
GitHub: https://github.com/fengbingchun/Messy_Test
總結(jié)
以上是生活随笔為你收集整理的C++11中std::tuple的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 矩阵特征分解介绍及雅克比(Jacobi)
- 下一篇: 矩阵奇异值分解简介及C++/OpenCV