Learning boost 2 Tuple and ref

Tuple

Boost::tuple是類似於std::pair的一個類。Pair有且只能有兩個成員(firstsecond),而tuple的元素可以是0-10個。

使用tuple要包含boost/tuple/tuple.hpp文件。

例如:

#include<boost/tuple/tuple.hpp>

...

tuple<int,double,string> t1(1,2.0,”Hello”);

tuple<int,char> t2(1,’a’);

tuple<int,int> t3;//在這種情況下,t3的兩個int值是爲定義

tuple<int,int> t4(1);//只初始化第一個元素

tuple的元素使用get<N>函數或get<N>成員函數訪問。例如:

tuple<int,double,string> t(1,2.0,”Hello”);

cout<<t.get<0>()<<endl;//輸出t的第一個元素,即 1

t.get<1>()=2.0;//t的第二個元素賦值爲2.0;

//以上都是使用get<N>成員函數,下面使用全局的get<N>函數

cout<<get<0>(t)<<endl;//

get<1>(t)=2.0;

tuple的元素還可以使用引用類型。例如:

int a;

tuple<&int,int> t(a,1);

t.get<0>()=123;

cout<<a<<endl;//這時應該輸出123

 

tuple<&int> t1;//這是錯的,引用類型一定要初始化

tuple<&int> t2(1);//這也是錯的,不能使用常數初始化引用類型

tuple還可以使用流直接輸出,但是一定要包含tuple_io.hpp文件。例如:

#include<boost/tuple/tuple_io.hpp>//tuple_io.hpp中已經包含tuple.hpp文件

tuple<int,string,double> t(2,”hello”,1.0);

cout<<t<<endl;//輸出(2 hello 1.0)

//tuple默認使用’(‘開始,’)’結尾,空格分隔的方式輸出。可以使用操縱器改變。

cout<<tuples::set_open('[')

     <<tuples::set_close(']')

     <<tuples::set_delimiter(',')

     <<t<<endl;//輸出[2,hello,1.0]

tuple同樣有==!=><等比較運算符的重載,大於小於的使用字典順序比較。

pair一樣,tuplemake_tuple輔助函數來構造tuple。例如:

cout<<make_tuple(1,1.0,”aaa”)<<endl;//構造了tuple<int,double,const char*>

如果要構造引用類型,要使用ref輔助函數。例如:

int a=123;

cout<<make_tuple(1,ref(a))<<endl;//構造了tuple<int,int&>

cout<<make_tuple(1,cref(a))<<endl;// 構造了tuple<int,const int&>

 

int a,b,c;

tuple<int&,int&,int&> t(a,b,c);

t=make_tuple(1,2,3);//這時a==1 b==2 c==3

對於這樣的應用,可以使用更爲方便的tie函數。例如:

int a,b,c;

tie(a,b,c)=make_tuple(1,2,3);

如果要其中的某幾個元素,可以使用tuples::ignore代替不需要使用的部分。例如:

tie(a,tuples::ignore,c)=make_tuple(1,2,3);

tuple的性能:

     cout<<sizeof(tuple<>)<<endl;         //   1

     cout<<sizeof(tuple<int>)<<endl;      //   4

     cout<<sizeof(tuple<int,int>)<<endl;  //   8

     cout<<sizeof(tuple<int,char>)<<endl;//    8

     cout<<sizeof(tuple<double>)<<endl;   //   8

     cout<<sizeof(tuple<int,double>)<<endl;//16

tuple的訪問,也是和pair具有相同的效率。

 

Ref

tuple中,我們使用到了refcref輔助函數,那麼ref到底是什麼呢?

ref(a),其實是返回了一個reference_wrapper<T>類,這個類保存着指向a的指針。

template<class T> class reference_wrapper

{

public:

    typedef T type;

 

#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)

    explicit reference_wrapper(T& t): t_(&t) {}

#else

    explicit reference_wrapper(T& t): t_(boost::addressof(t)) {}

#endif

 

    operator T& () const { return *t_; }

    T& get() const { return *t_; }

    T* get_pointer() const { return t_; }

 

private:

    T* t_;

};

以上就是reference_wraper的全部代碼。其中operator T&()const返回的是*t_的應用,那麼對於reference_wrapper的任何操作都會施加於*t_,通過reference_wrapper可以將某些值傳遞的參數轉換成引用傳遞。例如:

#include<iostream>

#include<boost/ref.hpp>

using namespace std;

using namespace boost;

template<class T> void inc(T t)

{

     ++t;//由於reference_wrapper並沒有重載++運算符,所有被隱式轉換爲int&,也就是對a的引用。

}

int main()

{

    int a=1;

     inc(ref(a));//構造reference_wrapper<int>

     cout<<a<<endl;//輸出2

     return 0;

}

有了reference_wrapper,我們可以輕鬆構造引用語義的stl容器,注意vector<int&>是錯誤的哦。

     vector<reference_wrapper<int> > ref_vector;

     int a[10];

     for (int i=0;i<10;++i)

         ref_vector.push_back(ref(a[i]));

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章