boost 實用工具

boost 實用工具

1. noncopyable P110

  • 實現一個禁止複製的類

        #include <boost/noncopyable.hpp>
        //or 
        //#include <boost/utility.hpp>
        class do_not_copy: boost::noncopyable
        {...};  

2. typeof P112

  • typeof庫使用宏模擬了C++0x新增加的typeof和auto關鍵字,可以減輕書寫煩瑣的變量類型聲明的工作,簡化代碼。

            #include <boost/typeof/typeof.hpp>
    
            vector<string> func()
            {
                vector<string> v(10);
                return v;
            }
    
            int main()
            {
                BOOST_TYPEOF(2.0*3) x = 2.0*3;
                BOOST_AUTO(y, 2+3);
    
                BOOST_AUTO(&a, new double[20]);  //VS2015編譯不過
                BOOST_AUTO(p, make_pair(1, "string"));
    
                BOOST_AUTO(v, func());
    
                return 0;
            }
  • 向typeof庫註冊自定義類

        #include <boost/typeof/typeof.hpp>
        #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
        namespace ex
        {
            struct demo_class {int a,b;};   //一個簡單的類
        }
        BOOST_TYPEOF_REGISTER_TYPE(ex::demo_class) //向typeof庫註冊類
    
        int main()
        {
            BOOST_AUTO(x, make_pair("test", ex::demo_class()));
            cout<<typeid(x).name()<<endl;
            x.second.a=10;
            x.second.b = 20;
            cout<<x.second.a<<x.second.b<<endl;
        }

3. optional P116

  • optional 庫使用“容器”語義,包裝了“可能產生無效值”的對象,實現了“未初始化”的概念。
  • 就地創建,減少拷貝做代價 這個有使用價值

        #include <boost/optional.hpp>
        #include <boost/utility/in_place_factory.hpp>
        using namespace boost;
    
        int main()
        {
            //就地創建string對象,不需要臨時對象string("....")
            optional<string> ops(in_place("test in_place_factory"));
            cout<< *ops;
            //就地創建std::vector對象,不需要臨時對象vector(10,3)
            optional<vector<int> > opp(in_place(10,3));
            assert(opp-size() == 10 );
            assert((*opp)[0] == 3);
        }

4. assign

  • 爲容器初始化或者賦值提供一個方法

    operator+=

        // 優點: 可應用與stl中定義的標準容器(vector, list, set, map等)
            // 缺點: 對於其他類型的容器(如boost新容器)則無能爲力
            void test_assign_plus()
            {
                using namespace boost::assign;
    
                // 1. vector
                std::vector<int> values;
                values += 1, 2, 3, 4, 5, 6, 7, 8, 9; // 插入值到容器的末尾
    
                BOOST_ASSERT(values.size() == 9);
                BOOST_ASSERT(values[0] == 1);
                BOOST_ASSERT(values[8] == 9);
    
                // 2. set 
                std::set<std::string> s;    //標準集合容器
                s += "cpp", "java", "c#", "python";
                BOOST_ASSERT(s.size() == 4);
    
                // 3. map
                std::map<int, std::string> m;
                m += std::make_pair(1, "one"), 
                     std::make_pair(2, "two"), 
                     std::make_pair(3, "three"), 
                     std::make_pair(4, "four");
                BOOST_ASSERT(m[1] == "one");
                BOOST_ASSERT(m[2] == "two");
                BOOST_ASSERT(m[3] == "three");
                BOOST_ASSERT(m[4] == "four");
            }

    operator()

            // 優點: operator+=使用上有些小的限制,而且在處理map容器也顯麻煩,操作符operator()更通用.
            //       不能直接使用operator(), 而應當使用assign庫提供三個輔助函數insert(),push_front(),push_back().
            //       這些函數可作用於擁有同名成員函數的容器,接受容器變量作爲參數
            //       返回一個代理對象list_inserter,它重載了operator(),=等操作符用來實現向容器填入數據的功能。
            void test_assign_bracket()
            {
                using namespace boost::assign;
    
                std::vector<int> v;
                push_back(v), 1, 2, 3, 4, 5;
                push_back(v), 6, 7, 8;
                std::copy(v.cbegin(), v.cend(), std::ostream_iterator<int>(std::cout, " "));
                std::cout << std::endl;
    
                std::vector<int> l;
                push_back(l), 1, 2, 3, 4, 5;
                push_back(l), 6, 7, 8;
                std::copy(l.cbegin(), l.cend(), std::ostream_iterator<int>(std::cout, " "));
                std::cout << std::endl;
    
                std::deque<int> d;
                push_back(d), 1, 2, 3, 4, 5;
                push_back(d), 6, 7, 8;
                push_front(d), 0, -1, -2;
                std::copy(d.cbegin(), d.cend(), std::ostream_iterator<int>(std::cout, " "));
                std::cout << std::endl;
    
                std::map<std::string, int> months;
                insert(months)
                    ( "january",   31 )( "february", 28 )
                    ( "march",     31 )( "april",    30 )
                    ( "may",       31 )( "june",     30 )
                    ( "july",      31 )( "august",   31 )
                    ( "september", 30 )( "october",  31 )
                    ( "november",  30 )( "december", 31 );
                BOOST_ASSERT(months.size() == 12);    
                BOOST_ASSERT(months["january"] == 31);
            }

    初始化容器元素的函數: list_of(), map_list_of(), tuple_list_of()

            // 操作符+=和()解決了對容器的賦值問題,但有的時候需要在容器構造的時候就完成數據的填充,這種方式較賦值更爲高效。
            // c++內建的數組和標準字符串類string支持這樣做,但stl容器則不行。
    
            // list_of()函數的用法與之前的insert(),push_back()等函數很相似, 也重載了括號, 逗號操作符。
            // 它很智能, 返回一個匿名的列表, 可以賦值給任意容器。
            void test_assign_list_of()
            {
                using namespace boost::assign;
    
                const std::list<int> l = list_of(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11);
                BOOST_ASSERT( l.size() == 11 );
                BOOST_ASSERT( l.back() == 11 );
                BOOST_ASSERT( l.front() == 1 );
    
                // 二維數組
                std::vector<std::vector<int>> v = list_of(list_of(1)(2)) (list_of(3)(4));
                v += list_of(5)(6), list_of(7)(8);
    
                // 兩個類似功能的ref_list_of()和cref_list_of(), 
                // 這兩個函數接受變量的引用作爲參數來創建初始化匿名列表,較list_of()的效率更高
                int a = 1, b = 2, c = 3;
                std::vector<int> v = ref_list_of<3>(a)(b)(c);
                assert(v.size() == 3);
            }
    
            void test_assign_map_list_of()
            {
                using namespace boost::assign;
    
                std::map<int, int> m1 = map_list_of(1, 2)(3, 4)(5, 6)(7, 8)(9, 10);
                std::map<int, std::string> m2 = map_list_of(1, "one")(2, "two")(3, "three")(4, "four");
    
            }

    assign庫提供repeat(),repeat_fun()和range()三個函數來減少重複的輸入

            void test_assign_repeat()
            {
                using namespace boost::assign;
    
                std::vector<int> v = list_of(1).repeat(3, 2)(3)(4)(5);
                // 1, 2, 2, 2, 3, 4, 5
                std::copy(v.cbegin(), v.cend(), std::ostream_iterator<int>(std::cout, " "));
                std::cout << std::endl; 
    
                std::deque<int> d;
                push_front(d).range(v.begin(), v.begin() + 5);
                // 3, 2, 2, 2, 1
                std::copy(d.cbegin(), d.cend(), std::ostream_iterator<int>(std::cout, " "));
                std::cout << std::endl;
            }

5. swap P128

boost::swap是對標準庫中的std::swap的增強和泛化

int a1[100];
int a2[10];
std::fill_n(a1,10,5);
std::fill_n(a2,10,2);
boost::swap(a1,a2);

特化std::swap P130
特化ADL可找到的swap

6. singleton 單件模式 P131

  • singleton_default 泛型單件類
        #include <boost/pool/detail/singleton.hpp>
        using boost::details::pool::singleton_default;  //單件名字空間

        class point
        {
        public:
            point(int a=0, int b=0, int c=0):x(a),y(b),z(c)
            {cout<<"point ctor"<<endl;}
            ~point()
            {cout<<"point dtor"<<endl;}
            //...
        };

        int main()
        {
            cout<<"main() start"<<endl;
            typedef singleton_default<point> origin;    //定義單件

            origin::instance().print();               //使用instance()獲得單件對象
            cout<<"main() finish"<<endl;
        }

        //例2

        class SqlDB_t
        {
        public:
            void connect()
            {cout<<"connect db"<<endl;}
            void exec(const char* sqlstr)
            { cout<<"exec insert/update/delete:"<<sqlstr<<endl; }
            void query(const char* sqlstr)
            {cout<<"exec select "<<sqlstr<<endl;}
        }

        typedef singleton_default<SqlDB_t> SqlDB;

        int main()
        {
            cout << "main() start"<<endl;
            SqlDB::instance().connect();
            SqlDB::instance().exec("create table goods(int id,varchar name(20)");
            SqlDB::instance().exec("insert into goods values(101, 'wii')");
            SqlDB::instance().query("select * from goods");
            cout<<"main() finish"<<endl;
        }

7. boost.serialzation 單件模式 P134

  • get_const_instance() 線程安全, get_mutable_instance()非線程安全,會出現競爭問題
  • 有兩種使用模式,參見例子

    
        #include <boost/serialization/singleton.hpp>
        using boost::serialization::singleton;
    
        //例1
        class point{...};
    
        ///////////////////////////
        //例2
        class point:public singleton<point>   //注意這裏
        {};
        ////////////////////
    
        int main()
        {
            cout<<"main() start"<<endl;
            typedef singleton<point> origin;    //單件類定義
    
            origin::get_const_instance().print();  //常對象
            origin::get_mutable_instance().print();//可變對象
    
            cout << "main() finish" <<endl;
        }   

8. tribool –基於三態的布爾邏輯 P136

  • optional、tribool的選擇方式:如果返回值可能是無效的(不存在有效的返回值),選optional;如果返回值總是確定的,但可能無法確定其意義,那麼就是tribool.

9. operators P140

操作符重載的最小實現

  • equality_comparable : 要求提供==,可自動實現!=,相等語義
  • less_than_comparable : 要求提供<,可自動實現>、<=、>=;
  • addable : 要求提供+=,可自動實現+;
  • subtractable : 要求提供-=,可自動實現-;
  • incrementable : 要求提供前置++,可自動實現後置++;
  • decrementable : 要求提供前置–,可自動實現後置–;
  • equivalent : 要求提供<,可自動實現==,等價語義。

        #include <boost/operators.hpp>
        class point:
            boost::less_than_comparable<point>      //小於關係,私有繼承
        {
        public:
            friend bool operator<(const point& l, const point& r)
            {
                retrun (l.x*l.x+l.y*l.y+l.z*l.z < r.x*r.x+r.y*r.y+r.z*r.z);
            }
    
            ...
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章