Boost 第七章 容器与数据结构

本文章所有内容源于《BOOST程序库完全开发指南:深入C++“准”标准库(第3版)》第七章


1. array

1.1 功能:

数组

1.2 头文件:

#include <boost/array.hpp>
using namespace boost;

1.3 用法:

using namespace std;
#include <boost/array.hpp>
using namespace boost;
#include <iostream>
//
void case1()
{
    array<int, 10> ar;

    ar[0] = 1;
    ar.back() = 10;	//访问最后一个元素
    assert(ar[ar.max_size() - 1] == 10);

    ar.assign(777);	//所有元素赋值为777
    for (auto x : ar)		//for+auto遍历元素
    {   std::cout << x << ",";   }

    int *p = ar.c_array();			//获得原始数组指针
    *(p + 5) = 253;						//指针算术运算
    std::cout << ar[5] << std::endl;

    ar.at(8) = 666;				//使用at函数访问元素
    std::sort(ar.begin(), ar.end());		//使用标准算法排序

}

//
#include <boost/assign.hpp>

void case2()
{
    array<std::string, 3> ar = {"alice","bob", "carl"};		//数组处死绘画

    int a[10] = {0};		//普通数组初始化
    array<int, 10> ar1 = {0};		//array初始化
    assert(std::equal(ar1.begin(), ar1.end(), a));			//两者的值同为全0

    array<std::string, 3> ar2 = {"racer"};			//初始化第一个元素
    assert(ar2.at(1).empty());				//第二个元素缺省构造,是个空字符串

    using namespace boost::assign;
    array<int, 3> arr(list_of(2)(4)(6)) ;			//只能用list_of

    for (auto i = 0u;i< arr.size() ;++i)
    {   std::cout << arr[i] << ",";}

}
//

int main()
{
    case1();
    case2();
}

2. dynamic_bitset

2.1 功能:

vector可以动态增长,但不能方便地仅为运算; bitset可以方便地容纳二进制位做位运算,但不能动态增长。

2.2 头文件:

#include <boost/dynamic_bitset.hpp>
using namespace boost;

2.3 用法:

#include <std.hpp>
using namespace std;

#include <boost/core/lightweight_test.hpp>
#include <boost/utility.hpp>
#include <boost/dynamic_bitset.hpp>
using namespace boost;

//
void case1()
{
    dynamic_bitset<> db1;	//空的dynamic_bitset
    dynamic_bitset<> db2(10);//大小为10的dynamic_bitset
    dynamic_bitset<> db3(0x16,
    BOOST_BINARY(10101));       //注意这里//大小为22的dynamic_bitset
    dynamic_bitset<> db4(string("0100")); //字符串构造
    dynamic_bitset<> db5(db3);	//拷贝构造

    dynamic_bitset<> db6;
    db6 = db4;		//赋值操作符

    cout << hex << db5.to_ulong() << endl;			//转换为整数
    cout << db4[0] << db4[1] << db4[2] << endl;

}

//
void case2()
{
    dynamic_bitset<> db;//大小为空的dynamic_bitset

    db.resize(10, true);//扩展为10个二进制位,数值全为1
    cout << db << endl; //输出1111111111

    db.resize(5);//缩小容量为5
    cout << db << endl;//输出11111

    {
        dynamic_bitset<> db(5,BOOST_BINARY(01110));

        cout << db << endl;//输出01110
        assert(db.size() == 5);//目前有5个二进制位

        db.clear();//清空dynamic_bitset
        assert(db.empty()&& db.size()==0);//判断dynamic_bitset是否为空

    }

    assert(dynamic_bitset<>(64).num_blocks()==1);
    assert(dynamic_bitset<>(65).num_blocks()==2);

    {
        dynamic_bitset<> db(5,BOOST_BINARY(01001));
        db.push_back(true);
        assert(db.to_ulong() == BOOST_BINARY_UL(101001));

    }

    {
        dynamic_bitset<> db(5,BOOST_BINARY(01001));
        db.append(BOOST_BINARY(101));
        assert(db.size() == sizeof(unsigned long)*8 + 5);
        cout << db << endl;             //0000000000000000000000000000010101001

    }
}

//
void case3()
{
    dynamic_bitset<> db1(4, BOOST_BINARY(1010));

    db1[0] &= 1;//按位与运算
    db1[1] ^= 1;//按位异或运算
    cout << db1 << endl;//1000

    dynamic_bitset<> db2(4, BOOST_BINARY(0101));
    assert(db1 > db2);

    cout << (db1 ^ db2) << endl;//1101
    cout << (db1 | db2) << endl;//1101

}

//
void case4()
{
    dynamic_bitset<> db(4, BOOST_BINARY(0101));

    assert(db.test(0) && !db.test(1));
    assert(db.any() && !db.none());
    assert(db.count() == 2);

    {
        dynamic_bitset<> db(4, BOOST_BINARY(0101));

        db.flip();	//反转所有二进制位
        assert(db.to_ulong() == BOOST_BINARY(1010));

        db.set();//至所有位为1
        assert(!db.none());//此时无0二进至位

        db.reset();//至所有位为0
        assert(!db.any() );//此时无1二进至位

        db.set(1, 1);//设置db[1]的值为1
        assert(db.count() == 1);

    }

    {
        dynamic_bitset<> db(5, BOOST_BINARY(00101));

        auto pos = db.find_first();
        assert(pos == 0);

        pos = db.find_next(pos);
        assert(pos == 2);

    }
}

//
void case5()
{
    cout << dec;

    dynamic_bitset<> db(10, BOOST_BINARY(1010101));
    cout << db.to_ulong() << endl;      //85
    assert(db.to_ulong() == 85);

    db.append(10);   //追加一个整数
    cout << db.to_ulong() << endl;
    assert(db.to_ulong() == 10325);//10325

    db.push_back(1);//追加一个二进制位,超过ulong的上限//抛出异常
    //BOOST_TEST_THROWS(db.to_ulong(), std::overflow_error);
    try
    {
        cout << db.to_ulong() << endl;
    }
    catch(std::overflow_error &)
    {
        cout << "can't convert to ulong."<< endl;
    }

    string str;
    to_string(db, str);
    cout << str << endl;

    dump_to_string(db , str);
    cout << str << endl;
}

//
void case6()
{
    dynamic_bitset<> db1(5, BOOST_BINARY(10101));
    dynamic_bitset<> db2(5, BOOST_BINARY(10010));

    cout << (db1 | db2) << endl;
    cout << (db1 & db2) << endl;
    cout << (db1 - db2) << endl;

    dynamic_bitset<> db3(5, BOOST_BINARY(101));
    assert(db3.is_proper_subset_of(db1));

    dynamic_bitset<> db4(db2);
    assert(db4.is_subset_of(db2));
    assert(!db4.is_proper_subset_of(db2));
}

//
void func(int n)
{
    //cout << "test " << n << endl;

    dynamic_bitset<> db(n);
    db.set();
    //cout << db.size() << endl;

    for (auto i = db.find_next(1);
         i != dynamic_bitset<>::npos ;
         i = db.find_next(i ) )
    {
        for (auto j = db.find_next(i);
             j != dynamic_bitset<>::npos ;
             j = db.find_next(j ))
        {
            if ( j % i == 0)
            {
                db[j] = 0;
            }
        }
    }

    cout << dec ;
    for (auto i = db.find_next(2);
            i != dynamic_bitset<>::npos ;
            i = db.find_next(i) )
    {
        cout << i << ", ";
    }

    cout << endl;
}

void case7()
{
    func(10);
    func(50);
}

int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
    case6();
    case7();
}

3. unordered

3.1 功能:

散列容器(hash container)是一种非常重要的容器类型,它比二叉树的存储方式可以提供更高的访问效率。

3.2 头文件:

#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
using namespace boost;

3.3 用法:

#include <iostream>
using namespace std;

#include <boost/assign.hpp>
#include <boost/unordered_set.hpp>      //boost的hash集合
#include <boost/unordered_map.hpp>
using namespace boost;

//
//基本用法
void case1()
{
    unordered_set<int > s = {1,2,3,4,5};            //初始化数据

    for (auto x : s)                                                         //for循环遍历集合
    {   cout << x << " ";   }
    cout << endl;
    cout << s.size() << endl;                                       //获取容器大小

    s.clear();                                                                      //清空集合
    cout << s.empty() << endl;                                  //判断集合是否为空

    s.insert(8);                                                                  //使用insert()函数
    s.insert(45);
    cout << s.size() << endl;
    cout << *s.find(8) << endl;                                     //查找元素

    s.erase(45);                                                                //删除元素

    using namespace boost::assign;                              //初始化hash集合
    unordered_set<int> us1 = list_of(1)(2)(3);
    unordered_set<int> us2 = list_of(3)(2)(1);
    assert(us1 == us2 );

}

//
void case2()
{
    typedef complex<double> complex_t;
    unordered_set<complex_t> s;

    s.emplace(1.0, 2.0);
    s.emplace(3.0, 4.0);

    for(auto& x : s)
    {    cout << x << ",";}
    cout << endl;

    s.emplace_hint(s.begin(), 5.0, 6.0);
    for(auto& x : s)
    {    cout << x << ",";}

}


//
//散列映射用法
void case3()
{
    using namespace boost::assign;//初始化

    unordered_map<int, string> um =
        map_list_of(1,"one")(2, "two")(3, "three");

    um.insert(make_pair(10,"ten")); //使用insert()函数
    cout << um[10] << endl;
    um[11] = "eleven";                                                 //关联数组用法
    um[15] = "fifteen";

    auto p = um.begin();                                                //获得迭代器
    for (; p != um.end(); ++p)
    {   cout << p->first << "-" << p->second << ",";    }
    cout << endl;

    um.erase(11);                                                           //删除数值为11的元素
    cout << um.size() << endl;                                          //输出5

    unordered_map<int, string> um1 = map_list_of(1,"11")(2,"22");
    unordered_map<int, string> um2 = map_list_of(1,"one")(2,"two");
    assert(um1 != um2);

}

//
void case4()
{
    typedef complex<double> complex_t;
    typedef unordered_map<int,complex_t> um_t;
    um_t s;

    s.emplace(boost::unordered::piecewise_construct,
        make_tuple(1),make_tuple(1.0, 2.0));
    s.emplace(boost::unordered::piecewise_construct,
        make_tuple(3),make_tuple(3.0, 4.0));

    for(auto& x: s)
    {
            cout << x.first << "<->" << x.second << ",";
    }
    cout << endl;

    s.emplace_hint(s.begin(),
    boost::unordered::piecewise_construct,
        make_tuple(5),make_tuple(5.0, 6.0));
    for(auto& x: s)
    {
            cout << x.first << "<->" << x.second << ",";
    }

}

//
void case5()
{
    using namespace boost::assign;

    unordered_set<int> us = (list_of(1),2,3,4);
    cout << us.bucket_count() << endl;

    for (size_t i = 0; i < us.bucket_count(); ++i)
    {   cout << us.bucket_size(i) << ",";   }

}
//
int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
}

4. bimap

4.1 功能:

映射型容器map和multi_map,就像一个关联数组,把一个元素key映射到另一个元素value,单向的智能从key到alue。
bimp可以容纳两个类型的元素,是这两种元素关系的集合,这是bimap的基本视图。还可以有左右视图,用left和right访问。

4.2 头文件:

#include <boost/bimap.hpp>
using namespace boost;

4.3 用法:

using namespace std;
#include <iostream>
#include <boost/bimap.hpp>
#include <boost/bimap/vector_of.hpp>
#include <boost/bimap/list_of.hpp>
#include <boost/bimap/multiset_of.hpp>
#include <boost/bimap/unordered_set_of.hpp>
#include <boost/bimap/unordered_multiset_of.hpp>
#include <boost/bimap/unconstrained_set_of.hpp>
using namespace boost;

//
//基本用法
void case1()
{
    bimap<int, string> bm;//定义一个双向视图对象

    bm.left.insert(make_pair(1, "111"));//左视图插入数据
    bm.left.insert(make_pair(2, "222"));

    bm.right.insert(make_pair("string", 10));//右视图插入数据
    bm.right.insert(make_pair("bimap", 20));

    for (auto pos = bm.left.begin();    //左视图迭代器迭代
            pos != bm.left.end();++pos)
    {
        cout << "left[" << pos->first << "]="
            << pos->second << endl;
    }

    //bm.right.begin()->second = 234;
    //在不是用视图的情况下插入bimap
    {
        bimap<int, string> bm;
        typedef decltype(bm)::value_type vt;
        bm.insert(vt(3, "333"));

    }
}

//
using namespace boost::bimaps;
bimap<int, unordered_set_of< string> > bm1;

bimap< multiset_of<int>, multiset_of< string> > bm2;

bimap< unordered_set_of<int>, list_of< string> > bm3;

bimap< vector_of<int>, unconstrained_set_of< string> > bm4;

template<typename T>
void print_map(T &m)
{
    for (auto& x : m)
    {   cout << x.first << "<-->"<< x.second << endl;   }
}


void case2()
{
    bimap<unordered_multiset_of<int>, unordered_multiset_of< string> > bm;

    bm.left.insert(make_pair(1, "111"));
    bm.left.insert(make_pair(2, "222"));
    bm.left.insert(make_pair(2, "555"));

    bm.right.insert(make_pair("string", 10));
    bm.right.insert(make_pair("bimap", 20));
    bm.right.insert(make_pair("bimap", 2));

    print_map(bm.left);

    {
        bimap<set_of<int>, vector_of<string> > bm;

        bm.left.insert(make_pair(1, "111"));
        bm.left[2] = "222";
        bm.left[300] = "bimap";

        //bm.right.insert(make_pair("string", 10));

        print_map(bm.left);

    }
}

//
bimap<tagged<int, struct id>, vector_of<string> >       bm11;
bimap<multiset_of<tagged<int, struct id> >,
        unordered_set_of<tagged< string, struct name> > >       bm12;

void case3()
{
    bimap<tagged<int, struct id>, tagged< string, struct name> > bm;

    bm.by<id>().insert(make_pair(1, "samus"));
    bm.by<id>().insert(make_pair(2, "adam"));

    bm.by<name>().insert(make_pair("link", 10));
    bm.by<name>().insert(make_pair("zelda", 11));

    print_map(bm.by<name>());
}

//
#include <boost/assign.hpp>
void case4()
{
    using namespace boost::bimaps;
    typedef bimap<multiset_of<int>, vector_of<string> > bm_t;

    bm_t bm = assign::list_of<bm_t::relation>(1, "111")(2, "222");
    //bm_t bm = {{1, "111"},{2, "222"}};

    assign::insert(bm.left)(3, "333")(4, "444");
    assign::push_back(bm.right)("555", 5)("666", 6);

    auto left_pos  = bm.left.find(3);
    auto right_pos = bm.project_right(left_pos);
    cout << "right:[" << right_pos->first 
        << "]=" << right_pos->second;

}

//
#include <boost/bimap/support/lambda.hpp>
void case5()
{
    using namespace boost::bimaps;
    typedef bimap<int, string > bm_t;

    using namespace boost::assign;
    bm_t bm = assign::list_of<bm_t::relation>
        (1, "mario")(2, "peach");

    auto pos = bm.left.find(1);
    cout << "[" << pos->first
        << "]=" << pos->second << endl;
    auto pos2 = bm.right.find("peach");
    cout << "[" << pos2->first
        << "]=" << pos2->second << endl;

    //pos = bm.left.find(1);
    //bm.left.replace_key(pos, 111);
    //bm.left.replace_data(pos, "luigi");

    pos = bm.left.find(1);
    bm.left.modify_key(pos,_key = 111);
    bm.left.modify_data(pos,_data = "luigi");
}

//
void case6()
{
    using namespace boost::bimaps;
    typedef bimap<set_of<tagged<int,struct id> >, 
            multiset_of< tagged<string,struct name> > > bm_t;

    using namespace boost::assign;

    bm_t bm = assign::list_of<bm_t::relation>(1, "mario")(2, "peach");
        insert(bm.by<id>())(3, "wario")(4, "luigi");
        insert(bm.by<name>())("yoshi", 5)("olima", 6);

    auto right_pos = bm.by<name>().find("yoshi");
    auto left_pos  = bm.project<id>(right_pos);
    ++left_pos;
    cout << "left:[" << left_pos->get<id>() 
        << "]=" << left_pos->get<name>();

}

//
void case7()
{
    typedef bimap<int, string> bm_t;
    bm_t bm;
    bm.left.insert(bm_t::left_value_type(1, "one"));
    bm.right.insert(bm_t::right_value_type("two", 222));

}

//

int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
    case6();
    case7();
}

5. circular_buffer

5.1 功能:

实现循环缓冲区的数据结构,支持标准的容器操作,但是大小是固定的,当达到容器末尾时,将会自动循环利用容器的另一端空间

5.2 头文件:

#include <boost/circular_buffer.hpp>
using namespace boost;

5.3 用法:

6. tuple

6.1 功能:

tuple(元组)定义一个有固定数目元素的容器,每个元素类型都可以不相同。

6.2 头文件:

#include <boost/tuple/tuple.hpp>
using namespace boost;

6.3 用法:

#include <typeinfo>
//using namespace std;

#include <boost/core/ignore_unused.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp>
using namespace boost;

//
typedef tuple<int, std::string>    my_tuple1;
typedef tuple<int, my_tuple1> my_tuple2;

typedef tuple<void>             no_instance_t1;
typedef tuple<double(int)>  no_instance_t2;

void case1()
{
    typedef tuple<int, std::string, double> my_tuple;
    my_tuple t1;
    my_tuple t2(1, "123");
    my_tuple t3(t1);
    t2 = t3;

    int x = 10;
    tuple<int&> t4(x);

    {
        tuple<void*> t1;
        tuple<double(*)(int)> t2;
    }

    {
        boost::make_tuple(2, 3.0);
        boost::make_tuple(std::string(), std::vector<int>());

        int i;
        std::string s;
        tuple<int, std::string&>     t1       = boost::make_tuple(i, boost::ref(s));
        tuple<const int&, std::string&>  t2   = boost::make_tuple(boost::cref(i),boost::ref(s));

        boost::ignore_unused(t1, t2);
    }

}

//
void case2()
{
    auto t = make_tuple(1, "char[]", 100.0);

    assert(t.get<0>() == 1);
    assert(t.get<2>() == 100.0);

    std::cout << t.get<1>();
    std::cout << ++t.get<0>();

    std::cout << std::endl;

    get<0>(t);
    get<1>(t);

}

//
void case3()
{
    typedef boost::tuple<int ,double ,std::string> my_tuple;    //3-tuple

    my_tuple t1 = boost::make_tuple(1, 100.0, std::string("abc"));
    my_tuple t2 = boost::make_tuple(1, 200.0, std::string("def"));
    assert(t1 < t2);

    my_tuple t3(t2);
    assert(t2 == t3);
}

//
void case4()
{
    typedef boost::tuple<int ,double ,std::string> my_tuple;

    my_tuple t1(1, 2.0, "string");
    std::cout << t1 << std::endl;

    //std::cout << "please input tuple:";
    //std::cin >> t1;

    //std::cout << t1 << std::endl;
    std::cout << tuples::set_open('[') << tuples::set_close(']');
    std::cout << tuples::set_delimiter(',');
    std::cout << t1 << std::endl;

}

//
typedef tuple<int ,double ,std::string> my_tuple;

my_tuple func()
{   return boost::make_tuple(1, 2.0, "string");}

void case5()
{
    int i;double d;std::string s;
    tie(i, d, s) = func();
    std::cout << i;

    tie(tuples::ignore, d, tuples::ignore) = func();
}

//
#include <boost/assign.hpp>
void case6()
{
    typedef boost::tuple<int ,double ,std::string> my_tuple;
    using namespace boost::assign;

    std::vector<my_tuple> v = tuple_list_of(1, 1.0, "123")(2, 2.0, "456");
    assert(v.size() == 2);

    v += boost::make_tuple(3, 3.0, "789"),boost::make_tuple(4, 4.0, "abc");
    assert(v.size() == 4);

}

//
template <typename Tuple>
void print_tuple(const Tuple& t)
{
    std::cout << t.get_head() << ',';
    print_tuple(t.get_tail());
}
template<>
void print_tuple(const tuples::null_type&) {}

void case7()
{
    typedef boost::tuple<int , double ,std::string> t_type;
    t_type  t(1, 2.1, "string tuple");
    print_tuple(t);

}

//
template<typename Visitor, typename Tuple>
typename Visitor::result_type
visit_tuple(Visitor v, const Tuple &t)
{
    v(t.get_head());
    return visit_tuple(v, t.get_tail());
};

struct print_visitor
{
    typedef void result_type;
    template<typename T>
        result_type operator()(const T &t)
        {
            std::cout << t << ",";
        }
};
template<>
void visit_tuple//< print_visitor,  tuples::null_type>
    (print_visitor , const tuples::null_type &)
    {}

template<typename T>
struct max_visitor
{
    T *tmp;                                             //最大值
    max_visitor(T *t):tmp(t){}
    typedef void result_type;
    result_type operator()(const T &t)
    {   *tmp = *tmp < t? t : *tmp;  }
};

template<>
void visit_tuple//< max_visitor<double>,  tuples::null_type>
(max_visitor<double> , const tuples::null_type &)
{}

void case8()
{
    boost::tuple<int , double ,std::string>  t(1, 2.1, "string visitor");
    visit_tuple(print_visitor(), t);

    {
        boost::tuple<int, long, float, double> t(100, 5, 3.14, 314.15);
        double *max_value = new double(t.get_head());
        max_visitor<double> mv(max_value);
        visit_tuple(mv, t);
        std::cout << *max_value  << std::endl;
    }

    typedef boost::tuple<int , std::string> my_tuple1;
    typedef boost::tuple<int, my_tuple1> my_tuple2;

    assert(typeid(int) == typeid(tuples::element<0, my_tuple1>::type));
    assert(typeid(std::string) == typeid(tuples::element<1, my_tuple1>::type));
    std::cout << tuples::length<my_tuple2>::value << std::endl;

}

//

int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
    case6();
    case7();
    case8();
}

7. any

7.1 功能:

只保存一个元素,可以是任何类型

7.2 头文件:

#include <boost/any.hpp>
using namespace boost;

7.3 用法:

// Copyright (c) 2015
// Author: Chrono Law
#include <std.hpp>
using namespace std;

#include <boost/exception/all.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/assign.hpp>
#include <boost/any.hpp>
using namespace boost;

//
void case1()
{
    any a(10);

    int n = any_cast<int>(a);
    assert(n == 10);

    any_cast<int&>(a) = 20;
    assert(any_cast<int>(a) == 20);;

    try
    {
        any a;
        any_cast<int>(a);
    }
    catch(boost::exception&)
    {   
        cout << current_exception_diagnostic_information();
    }

    any a1, a2(2.0);
    assert(any_cast<int*>(&a1) == nullptr);
    assert(any_cast<string*>(&a2) == nullptr);

}

//
void case2()
{
    any a(100);
    a = string("char*");
    a = vector<vector<int> >();

    a = "c str";
    cout << a.type().name() << endl;
    cout << any_cast<const char*>(&a) << endl;
    cout << any_cast<const char*>(a) << endl;

    string *ps = new string("abc");     //不好的使用方式
    a = ps;
    if (!a.empty() && any_cast<string*>(a))
    {       cout << *any_cast<string*>(a)<< endl;   }

}

//
template<typename T>
bool can_cast(any &a)
{   return typeid(T) == a.type();}

template<typename T>
T& get(any &a)
{
    assert(can_cast<T>(a));
    return *any_cast<T>(&a);
}

template<typename T>
T* get_pointer(any &a)
{
    assert(can_cast<T>(a));
    return any_cast<T>(&a);
}

template<typename T>
any make_ptr_any(T *p = 0)
{   return any(boost::shared_ptr<T>(p));}

template<typename T>
boost::shared_ptr<T>& get_shared(any &a)
{
    assert(can_cast<boost::shared_ptr<T> >(a));
    return *any_cast<boost::shared_ptr<T> >(&a);
}

void case3()
{
    any a;
    int x = 1;
    a = x;
    assert(can_cast<int>(a));
    get<int>(a) = 10;
    *get_pointer<int>(a) = 20;

    a = make_ptr_any<string>(new string("long"));
    cout << *get_shared<string>(a) << endl;
    a = make_ptr_any<vector<int> >(new vector<int>);

}

//
template<typename T > struct any_print
{
    void operator()(any &a)
    try
    {
        cout << *any_cast<T>(&a) << endl;   
    }
    catch(bad_any_cast &)
    {
        cout << "print error" << endl;
    }

};

template<typename T >
struct any_print<boost::shared_ptr<T> >
{
    void operator()(any &a)
    try
    {
        cout << **any_cast<boost::shared_ptr<T> >(&a) << endl; 
    }
    catch(bad_any_cast &)
    {
        cout << "print error" << endl;
    }
};

void case4()
{
    any a;

    a = 10;
    any_print<int>()(a);

    auto ps = boost::make_shared<string>("metroid");
    a = ps;
    any_print< boost::shared_ptr<string> >()(a);

}

//
void case5()
{
    vector<any> v;
    v.push_back(10);                                    //int
    v.push_back(1.414);                                 //double
    v.push_back(boost::shared_ptr<int>(new int(100) ));    //shared_ptr

    using namespace boost::assign;
    vector<any> v2 = list_of<any>(10)(0.618)(string("char"));
    cout << v2.size();

}

//

int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
}

8. dynamic_bitset

8.1 功能:

vector可以动态增长,但不能方便地仅为运算; bitset可以方便地容纳二进制位做位运算,但不能动态增长。

8.2 头文件:

#include <boost/dynamic_bitset.hpp>
using namespace boost;

8.3 用法:

#include <std.hpp>
using namespace std;

#include <boost/core/lightweight_test.hpp>
#include <boost/utility.hpp>
#include <boost/dynamic_bitset.hpp>
using namespace boost;

//
void case1()
{
    dynamic_bitset<> db1;
    dynamic_bitset<> db2(10);
    dynamic_bitset<> db3(0x16,
    BOOST_BINARY(10101));       //注意这里
    dynamic_bitset<> db4(string("0100"));
    dynamic_bitset<> db5(db3);

    dynamic_bitset<> db6;
    db6 = db4;

    cout << hex << db5.to_ulong() << endl;
    cout << db4[0] << db4[1] << db4[2] << endl;

}

//
void case2()
{
    dynamic_bitset<> db;

    db.resize(10, true);
    cout << db << endl;

    db.resize(5);
    cout << db << endl;

    {
        dynamic_bitset<> db(5,BOOST_BINARY(01110));

        cout << db << endl;
        assert(db.size() == 5);

        db.clear();
        assert(db.empty()&& db.size()==0);

    }

    assert(dynamic_bitset<>(64).num_blocks()==1);
    assert(dynamic_bitset<>(65).num_blocks()==2);

    {
        dynamic_bitset<> db(5,BOOST_BINARY(01001));
        db.push_back(true);
        assert(db.to_ulong() == BOOST_BINARY_UL(101001));

    }

    {
        dynamic_bitset<> db(5,BOOST_BINARY(01001));
        db.append(BOOST_BINARY(101));
        assert(db.size() == sizeof(unsigned long)*8 + 5);
        cout << db << endl;             //0000000000000000000000000000010101001

    }
}

//
void case3()
{
    dynamic_bitset<> db1(4, BOOST_BINARY(1010));

    db1[0] &= 1;
    db1[1] ^= 1;
    cout << db1 << endl;

    dynamic_bitset<> db2(4, BOOST_BINARY(0101));
    assert(db1 > db2);

    cout << (db1 ^ db2) << endl;
    cout << (db1 | db2) << endl;

}

//
void case4()
{
    dynamic_bitset<> db(4, BOOST_BINARY(0101));

    assert(db.test(0) && !db.test(1));
    assert(db.any() && !db.none());
    assert(db.count() == 2);

    {
        dynamic_bitset<> db(4, BOOST_BINARY(0101));

        db.flip();
        assert(db.to_ulong() == BOOST_BINARY(1010));

        db.set();
        assert(!db.none());

        db.reset();
        assert(!db.any() );

        db.set(1, 1);
        assert(db.count() == 1);

    }

    {
        dynamic_bitset<> db(5, BOOST_BINARY(00101));

        auto pos = db.find_first();
        assert(pos == 0);

        pos = db.find_next(pos);
        assert(pos == 2);

    }
}

//
void case5()
{
    cout << dec;

    dynamic_bitset<> db(10, BOOST_BINARY(1010101));
    cout << db.to_ulong() << endl;      //85
    assert(db.to_ulong() == 85);

    db.append(10);
    cout << db.to_ulong() << endl;
    assert(db.to_ulong() == 10325);

    db.push_back(1);
    //BOOST_TEST_THROWS(db.to_ulong(), std::overflow_error);
    try
    {
        cout << db.to_ulong() << endl;
    }
    catch(std::overflow_error &)
    {
        cout << "can't convert to ulong."<< endl;
    }

    string str;
    to_string(db, str);
    cout << str << endl;

    dump_to_string(db , str);
    cout << str << endl;
}

//
void case6()
{
    dynamic_bitset<> db1(5, BOOST_BINARY(10101));
    dynamic_bitset<> db2(5, BOOST_BINARY(10010));

    cout << (db1 | db2) << endl;
    cout << (db1 & db2) << endl;
    cout << (db1 - db2) << endl;

    dynamic_bitset<> db3(5, BOOST_BINARY(101));
    assert(db3.is_proper_subset_of(db1));

    dynamic_bitset<> db4(db2);
    assert(db4.is_subset_of(db2));
    assert(!db4.is_proper_subset_of(db2));
}

//
void func(int n)
{
    //cout << "test " << n << endl;

    dynamic_bitset<> db(n);
    db.set();
    //cout << db.size() << endl;

    for (auto i = db.find_next(1);
         i != dynamic_bitset<>::npos ;
         i = db.find_next(i ) )
    {
        for (auto j = db.find_next(i);
             j != dynamic_bitset<>::npos ;
             j = db.find_next(j ))
        {
            if ( j % i == 0)
            {
                db[j] = 0;
            }
        }
    }

    cout << dec ;
    for (auto i = db.find_next(2);
            i != dynamic_bitset<>::npos ;
            i = db.find_next(i) )
    {
        cout << i << ", ";
    }

    cout << endl;
}

void case7()
{
    func(10);
    func(50);
}

int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
    case6();
    case7();
}

9. variant

9.1 功能:

一种可变类型,与any相似。

9.2 头文件:

#include <boost/variant.hpp>
using namespace boost;

9.3 用法:

#include <std.hpp>
using namespace std;

#include <boost/assign.hpp>
#include <boost/variant.hpp>
using namespace boost;

//
void case1()
{
    variant<int, float, string> v;
    v = "123";

    cout << v << endl;
}

//
void case2()
{
    typedef variant<int, double, string> var_t;

    var_t v(1);                                 //v->int
    v = 2.13;                                       //v->double
    assert(v.type() == typeid(double));

    var_t v2("string type");                        //v2->string
    cout << get<string>(v2);

    v2 = v;                                         //v2->double

    cout << get<int>(var_t(108));

}

//
void case3()
{
    typedef variant<int, double, string> var_t;
    var_t v;
    assert(v.type() == typeid(int));
    assert(v.which() == 0);

    v = "variant demo";
    cout << *get<string>(&v) << endl;

    try
    {
        cout << get<double>(v) << endl;
    }
    catch (bad_get &)
    {
        cout << "bad_get" << endl;
    }
}

//

struct var_print : public static_visitor<>
{
    template<typename T>
    void operator()(T &i) const
    {
        i *= 2;
        cout << i << endl;
    }

    void operator()(vector<int> &v) const
    {
        v.reserve(v.size()*2);
        copy(v.begin(),v.end(),back_inserter(v)) ;
        for (auto& x : v)
        {
            cout << x << ",";                       //输出以验证
        }
        cout << endl;
    }

};

void case4()
{
    typedef variant<int, double, vector<int> > var_t;

    var_t v(1);
    var_print vp;

    apply_visitor(vp, v);
    v = 3.414;
    apply_visitor(vp, v);

    //using namespace boost::assign;
    //v = vector<int>({1,2});
    vector<int> tmp = {1,2};
    v = tmp;
    apply_visitor(vp, v);

    auto vp2 = apply_visitor(vp);
    vp2(v);

}

//
template<BOOST_VARIANT_ENUM_PARAMS(typename T)>
void op_var(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& v)
{   cout << v << endl;}

#include <boost/mpl/vector.hpp>
void case5()
{
    typedef boost::mpl::vector<
        int, double, std::vector<string> > var_types;

    make_variant_over<var_types>::type v;
    v = 2.13;

}

//

int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
}

10. multi_array

10.1 功能:

多维数组

10.2 头文件:

#include <boost/multi_array.hpp>
using namespace boost;

10.3 用法:

#include <std.hpp>
using namespace std;

#include <boost/assign.hpp>
#include <boost/multi_array.hpp>
using namespace boost;

//
void case1()
{
    multi_array<int, 3> ma(extents[2][3][4]);

    auto shape = ma.shape();
    for (size_t i = 0; i < ma.num_dimensions(); ++i)
    {
        cout << shape[i] << ",";
    }
    cout << endl << ma.num_elements() << endl;

    for (int i = 0,  v = 0; i < 2; ++i)
        for (int j = 0; j < 3;++j)
            for (int k = 0;k < 4;++k)
            {
                ma[i][j][k] = v++;
            }

    for (int i = 0; i < 2; ++i)
    {
        for (int j = 0; j < 3;++j)
        {
            for (int k = 0;k < 4;++k)
            {
                cout << ma[i][j][k] << ",";
            }
            cout << endl;
        }
        cout << endl;
    }

    //cout << ma[2][3][4];

    std::array<size_t, 3> idx = {0,1,2};
    ma(idx) = 10;
    cout << ma(idx) << endl;
}

//
void case2()
{
    multi_array<int, 3> ma(extents[2][3][4]);
    assert(ma.shape()[0] == 2);

    std::array<std::size_t, 3> arr = {4,3,2};
    ma.reshape(arr);
    assert(ma.shape()[0] == 4);

    ma.resize(extents[2][9][9]);
    assert(ma.num_elements() == 2*9*9);
    assert(ma.shape()[1] == 9);
}

//
void case3()
{
    typedef multi_array<int, 2> ma_type;
    multi_array<int, 2> ma(extents[3][4]) ;

    typedef ma_type::index_range range;
    //indices[range(0,2)][range(0,2)];

    auto view = ma[indices[range(0,2)][range(0,2)] ];

    cout << view.num_elements() << endl;
    for (int i = 0; i < 2; ++i)
    {
        for (int j = 0; j < 2;++j)
        {
            cout << view[i][j] << ",";
        }
        cout << endl;
    }
    cout << *view.shape() << endl;

}

//
void case4()
{
    int arr[12];
    for (int i = 0;i < 12;++i)
    {   arr[i] = i; }

    multi_array_ref<int, 2> mar(arr, extents[3][4]);

    for (size_t i = 0; i < 3; ++i)
    {
        cout << "(";
        for(size_t j = 0;j < 4;++j)
        {
            cout << mar[i][j]++;
            cout << (j!=3?',':' ');
        }
        cout << ")" << endl;
    }

    const_multi_array_ref<int, 2> cmar(arr, extents[2][6]);

    for (size_t i = 0; i < 2; ++i)
    {
        cout << "(";
        for(size_t j = 0;j < 6;++j)
        {
            cout << cmar[i][j];
            cout << (j!=5?',':' ');
        }
        cout << ")" << endl;
    }

}

//
void case5()
{
    //multi_array<int, 3> ma(vector<int>(assign::list_of(2)(2)));
    multi_array<int, 3> ma(vector<int>{2,2,2});
    auto shape = ma.shape();
    for (size_t i = 0; i < ma.num_dimensions(); ++i)
    {
        cout << shape[i] << ",";
    }

}

//
void case6()
{
    typedef multi_array<int, 3> ma_type;
    typedef ma_type::extent_range range;
    ma_type ma(extents [range(1,5)][4][range(-2,2)]);
    ma[1][0][-2] = 10;

    ma.reindex(1);
    assert(ma[1][1][1] == 10);
    ma.reindex(std::array<int,3>{1,0,-4});
    assert(ma[1][0][-4] == 10);

    cout << *ma.index_bases() << endl;
}
//
void case7()
{
    using namespace boost::detail::multi_array;

    typedef multi_array<int, 3> ma_type;
    typedef ma_type::index_range range;
    ma_type ma(extents[9][8][7]);

    auto view = ma[indices[range()< 3L][2L<=range()<= 5L][range()] ];
    cout << *view.shape() << endl;

}
//

int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
    case6();
    case7();
}

11. property_tree

11.1 功能:

保存了多个属性值的树形数据结构,可以访问任意节点。读取xml文件,这个很重要。

11.2 头文件:

#include <boost/property_tree/ptree.hpp>
using namespace boost;

11.3 用法:

#include <std.hpp>
using namespace std;

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
using namespace boost::property_tree;

//
void case1()
{
    ptree pt;
    read_xml("conf.xml", pt);

    pt.get<string>("conf.theme");
    pt.get<int>("conf.clock_style");
    pt.get("conf.no_prop", 100);

    cout << pt.get<string>("conf.theme") << endl;
    cout << pt.get<int>("conf.clock_style") << endl;
    cout << pt.get<long>("conf.gui")<< endl;
    cout << pt.get("conf.no_prop", 100)<< endl;

    auto child = pt.get_child("conf.urls");
    for (auto& x : child)
    {   cout <<  x.second.get_value<string>() << ",";   }
    cout << endl;

    for(auto& x : pt.get_child("conf.urls"))
    {
        cout <<  x.second.data() << ",";
    }
    cout << endl;

}

//
void case2()
{
    ptree pt;
    read_xml("conf.xml", pt);

    pt.put("conf.theme", "Matrix Reloaded");
    pt.put("conf.clock_style", 12);
    pt.put("conf.gui", 0);
    //pt.put("conf.urls.url", "http://www.url4.org");
    pt.add("conf.urls.url", "http://www.url4.org");

    write_xml(cout , pt);
}

//
void case3()
{
    ptree pt;
    read_xml("conf.xml", pt);
    cout << pt.get<string>("conf.<xmlcomment>") << endl;
    cout << pt.get<string>("conf.clock_style.<xmlattr>.name") << endl;
    cout << pt.get<long>("conf.theme.<xmlattr>.id")<< endl;
    cout << pt.get<string>("conf.urls.<xmlcomment>")<< endl;

}
//
#include <boost/property_tree/json_parser.hpp>
void case4()
{
    ptree pt;
    read_json("conf.json", pt);

    cout << pt.get<string>("conf.theme") << endl;
    cout << pt.get<int>("conf.clock_style") << endl;
    cout << pt.get<long>("conf.gui")<< endl;
    cout << pt.get("conf.no_prop", 100)<< endl; 

    for (auto& x : pt.get_child("conf.urls"))
    {   cout <<  x.second.data() << ",";    }

}
//
int main()
{
    case1();
    case2();
    case3();
    case4();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值