本文章所有内容源于《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();
}