c++標準庫-c++通用工具

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 << "]";
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章