Pair 和 Tuple
c++11中 Tuple Class被重新實現,有了template可以接受不定實參的能力。可以接受任意大小的異質集合。
Class Pair仍舊爲兩個元素服務,用來組合一個雙元素的Tuple。
Pair
其可以將兩個value視爲一個單元。尤其容器map, multimap, unordered_map, unorder_multimap
就是使用pair管理其以key/value pair存在的元素。任何函數如果需要返回兩個value,也需要用到pair,列如minmax()
- 元素訪問
由struct定義,其成員都是public
namespace std{
template <typename T1, typename T2>
struct pair {
//membber
T1 first;
T2 second;
}
}
- pair的操作函數
操作函數 | 影響 |
---|---|
pair<T1,T2> p | defaulr構造函數,建立一個pair,元素類型分別爲T1,T2,各自以其default構造函數初始化 |
pair<T1,T2> p(vall,vall) | 建一個pair,元素類型分別爲T1,T2,以vall和vall爲初始值 |
pair<T1,T2> p(rev1,rev2) | 建一個pair,元素類型分別爲T1,T2,以rev1和rev2進行move式初始化(move initialized) |
pair<T1,T2> p(piecewise_construct,t1,t2) | 建立一個pair,元素分別爲tuple T1和T2,以tuple t1和t2爲初始值 |
pair<T1,T2> p(p2) | Copy構造函數,建立p成爲p2的拷貝 |
pair<T1,T2> p(rv) | Move構造函數,將rv的內容移動至p(允許隱式類型轉換) |
p=p2 | 將p2賦值給p(始自c++11,允許隱式類型轉換) |
p =rv | 將rv的值move assign給p(始自c++11,允許隱式類型轉換) |
p.first | 直接訪問成員一 |
p.second | 直接訪問成員二 |
get<0> (p) | 等價於p.first(始自c++11) |
get<1> (p) | 等價於p.second(始自c++11) |
p1 ==p2 | 返回p1和p2是否相等 |
p1!=p2 | 返回是否p1不等於p2 |
p1<p2 | 返回是否p1小於p2(比較first,如果相等則比較second) |
p1>p2 | 返回是否p1大於p2 |
p1 <=p2 | |
p1 >= p2 | |
p1.swap(p2) | 互換p1和p2的數據(始自c++11) |
swap(p1,p2) | 同上,全局函數(始自c++11) |
make_pair(val1, val2) | 返回一個pair,帶有val1和val2的類型和數據 |
舉個例子,實現一個泛型函數模板(generic function template),以來將一個value pair寫入一個stream:
template<typename T1, typename T2>
std::ostream &operator<<(std::ostream &strm, const std::pair<T1, T2> &p)
{
return strm << "[" << p.first << "," << p.second << "]";
}
cout << make_pair(1,1.23) << endl;
//輸出[1,1.23]
typedef std::pair<int,float > IntFloatPair;
IntFloatPair p(2, 1.234);
typedef std::pair<int, float> IntFloatPair;
IntFloatPair p(2, 1.234);
std::get<0>(p);//2
std::get<1>(p);//1.234
std::tuple_size<IntFloatPair>::value; //獲得元素的個數
std::tuple_element<0, IntFloatPair>::type; //獲得第一個元素的類型
#include <iostream>
#include <utility>
#include <tuple>
using namespace std;
class Foo {
public:
Foo (tuple<int, float>) {
cout << "Foo::Foo(tuple)" << endl;
}
template <typename... Args>
Foo (Args... args) {
cout << "Foo::Foo(args...)" << endl;
}
};
int main()
{
// create tuple t:
tuple<int,float> t(1,2.22);
// pass the tuple as a whole to the constructor of Foo:
pair<int,Foo> p1 (42, t);
// pass the elements of the tuple to the constructor of Foo:
pair<int,Foo> p2 (piecewise_construct, make_tuple(42), t);
}
Tuple
c++11使用variadic tempalte,使的template得以接受任何數量的template實參
#include <tuple>
#include <iostream>
#include <complex>
#include <string>
using namespace std;
int main()
{
// create a four-element tuple
// - elements are initialized with default value (0 for fundamental types)
tuple<string,int,int,complex<double>> t;
// create and initialize a tuple explicitly
tuple<int,float,string> t1(41,6.3,"nico");
// "iterate" over elements:
cout << get<0>(t1) << " ";
cout << get<1>(t1) << " ";
cout << get<2>(t1) << " ";
cout << endl;
// create tuple with make_tuple()
// - auto declares t2 with type of right-hand side
// - thus, type of t2 is tuple
auto t2 = make_tuple(22,44,"nico");//"nico"爲const char*
// assign second value in t2 to t1
get<1>(t1) = get<1>(t2);
// comparison and assignment
// - including type conversion from tuple<int,int,const char*> auto t2 = make_tuple(22,44,"nico")
// to tuple<int,float,string>
if (t1 < t2) { // compares value for value,字典比較序
t1 = t2; // OK, assigns value for value
}
}
使用模板超編程,實現在編譯器遞歸迭代tuple的所有元素。
#include <tuple>
#include <iostream>
// helper: print elements with index IDX and higher of tuple t having MAX elements
template <int IDX, int MAX, typename... Args>
struct PRINT_TUPLE {
static void print (std::ostream& strm, const std::tuple<Args...>& t) {
strm << std::get<IDX>(t) << (IDX+1==MAX ? "" : ",");
PRINT_TUPLE<IDX+1,MAX,Args...>::print(strm,t);
}
};
// partial specialization to end the recursion
template <int MAX, typename... Args>
struct PRINT_TUPLE<MAX,MAX,Args...> {
static void print (std::ostream& strm, const std::tuple<Args...>& t) {
}
};
// output operator for tuples,結束迭代的特例化函數
template <typename... Args>
std::ostream& operator << (std::ostream& strm,
const std::tuple<Args...>& t)
{
strm << "[";
PRINT_TUPLE<0,sizeof...(Args),Args...>::print(strm,t);
return strm << "]";
}