Boost 与c++  Boost是基于C++标准的现代库,他的源码按照Boost Software License 来发布,允许任何人自由使用、修改和分发。
Boost有哪些功能?  Boost强大到拥有超过90个库,但我们暂时只学习其中一部分
Any  boost::any是一个数据类型,他可以存放任意的类型,例如说一个类型为boost::any的变量可以先存放一个int类型的值,然后替换为一个std::string的类型字符串。
Array  好像是一个数组容器,和std::vector应该差别不大。
and more … 这个系列的博客来干嘛?  这个系列的博客用来介绍Boost提供的接口,不对Boost进行源码分析,关于Boost的源码,预计会在Boost源码分析笔记系列的博客中。
Boost.Any   Any在C++17被编入STL
在基本数据类型中玩弱类型 1 2 3 4 5 6 #include  <boost/any.hpp>  int  main ()   boost::any a = 1 ;   a = 3.14 ;   a = true ; } 
 这样的代码是允许编译的,大概是因为boost::any内部储存的是指针。
char数组不行了 1 2 3 4 5 #include  <boost/any.hpp>  int  main ()   boost::any a = 1 ;   a = "hello world" ; } 
 上诉代码可以编译和运行,但是一定会碰到问题的,当我们把char数组弄过去的时候,就不太行了,原因是char[]不支持拷贝构造,但是我们可以通过把std::string来解决这个问题。
用std::string代替char数组 1 2 3 4 5 #include  <boost/any.hpp>  int  main ()   boost::any a = 1 ;   a = std::string ("hello world" ); } 
 可以见到我们用string完美地解决了这个问题。
写很容易,如何读呢?  我们已经学习了boost::any的写操作,但是应该如何读取呢?
1 2 3 4 5 6 #include  <boost/any.hpp>  #include  <iostream>  int  main ()   boost::any a = 1 ;   std::cout << boost::any_cast <int >(a) << std::endl; } 
 boost提供了一个模版函数any_cast<T>来对我们的any类进行读取
类型不对会抛出异常  有了any<T>的模版,看起来我们可以对boost进行任意读取,我们试试下这个
1 2 3 4 5 6 7 #include  <boost/any.hpp>  #include  <iostream>  int  main ()    boost::any a = 1 ;   a = "hello world" ;   std::cout << boost::any_cast <int >(a) << std::endl; } 
 抛出了如下异常
1 libc++abi.dylib: terminating with uncaught exception of type boost::wrapexcept<boost::bad_any_cast>: boost::bad_any_cast: failed conversion using boost::any_cast 
 实际上上诉代码是永远无法成功的。因为你把一个char数组传了进去。
成员函数  boost的any是有很多成员函数的。比方说empty可以判断是否为空,type可以得到类型信息,
1 2 3 4 5 6 7 8 9 10 11 12 #include  <boost/any.hpp>  #include  <iostream>  #include  <typeinfo>  int  main ()    boost::any a = std::string ("asdf" );   if  (!a.empty ()) {     std::cout << a.type ().name () << std::endl;     a = 1 ;     std::cout << a.type ().name () << std::endl;   } } 
 代码运行结果如下,表示首先是字符串,然后是整形。
1 2 NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE i 
拿到指针  当我们把一个any的地址传给any_cast的时候,我们会得到any内部数据的指针,
1 2 3 4 5 6 7 8 9 #include  <boost/any.hpp>  #include  <iostream>  int  main ()   boost::any a = 1 ;   int  *i = boost::any_cast <int >(&a);   std::cout << *i << std::endl; } 
Boost::Tuple  boost::tuple是一个元组。在c++11被编入STL
第六行无法通过编译,这说明tuple的长度最长只能是10
第9-12行定义了3个元组
第13行演示了如何通过make_tuple构造元组
 第14行演示了如何通过get来访问元组里面的元素
 第16行演示了get的返回值是引用
 第19-20行演示了tuple的等号操作
 第23-27行演示了tuple中可以储存引用
 第28行通过tie构造了一个全引用元组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include  <boost/tuple/tuple.hpp>  #include  <boost/tuple/tuple_comparison.hpp>  #include  <boost/tuple/tuple_io.hpp>  #include  <bits/stdc++.h>  int  main ()       boost::tuple<int , int , int , int , int , int , int , int , int , int > a (         1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 )   boost::tuple<std::string, std::string> b ("hello" , "world" )  ;   boost::tuple<std::string, std::string> c ("hello" , "world2" )  ;   std::cout << boost::make_tuple (1 , 2 , 3 , 4 ) << std::endl;   std::cout << "a.get<0>() is "  << a.get <0 >() << std::endl;   std::cout << "a is "  << a << std::endl;   a.get <0 >() = -1 ;   std::cout << "a is "  << a << std::endl;   std::cout << "b is "  << b << std::endl;   std::cout << "b==c is "  << (b == c) << std::endl;   std::cout << "b==b is "  << (b == b) << std::endl;      int  x = 1 , y = 2 ;   boost::tuple<int &, int > reference (boost::ref(x), y)  ;      x = 5 ;   std::cout << "reference is "  << reference << std::endl;   auto  reference2 = boost::tie (x, y);   x = 10 , y = 11 ;   std::cout << "reference2 is "  << reference2 << std::endl; } 
输出
1 2 3 4 5 6 7 8 9 (1 2 3 4) a.get<0>() is 1 a is (1 2 3 4 5 6 7 8 9 10) a is (-1 2 3 4 5 6 7 8 9 10) b is (hello world) b==c is 0 b==b is 1 reference is (5 2) reference2 is (10 11) 
Boost::Variant  boost::variant和any很像,variant和any一样在C++17中被编入STL
 variant可以指定一部分数据类型,你可以在这一部分中随便赋值,就像下面写到的一样,另外和any的any_cast不一样的是variant使用get<T>来获得内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include  <boost/variant.hpp>  #include  <iostream>  #include  <string>  int  main ()    boost::variant<double , char , std::string> v;   v = 3.14 ;   std::cout << boost::get <double >(v) << std::endl;   v = 'A' ;      std::cout << boost::get <char >(v) << std::endl;   v = "Hello, world!" ;   std::cout << boost::get <std::string>(v) << std::endl; } 
访问者模式  variant允许我们使用访问者模式来访问其内部的成员,使用函数boost::apply_visitor来实现,访问者模式使用的时候重载仿函数。仿函数记得继承static_visitor即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include  <boost/variant.hpp>  #include  <iostream>  #include  <string>  struct  visit  : public  boost::static_visitor<> {  void  operator () (double  &d)  const  "double"  << std::endl; }   void  operator () (char  &c)  const  "char"  << std::endl; }   void  operator () (std::string &s)  const  "string"  << std::endl; } }; int  main ()    boost::variant<double , char , std::string> v;   v = 3.14 ;   boost::apply_visitor (visit (), v);   v = 'A' ;   boost::apply_visitor (visit (), v);   v = "Hello, world!" ;   boost::apply_visitor (visit (), v); } 
输出
StringAlgorithms  我终于找到一个暂时没有被编入C++17的库了,听说在C++20中他也没进,哈哈哈。
大小写转化  首先上来的肯定就是大小写转化啦,使用函数to_upper_copy(string)就可以了。
1 2 3 4 5 6 7 8 #include  <boost/algorithm/string.hpp>  #include  <iostream>  int  main ()    std::string s = "abcdefgABCDEFG" ;   std::cout << boost::algorithm::to_upper_copy (s) << std::endl;   std::cout << boost::algorithm::to_lower_copy (s) << std::endl; } 
删除子串  erase_all_copy就是说先copy一份,然后再将子串全部删除,如果不带copy就是说直接操作穿进去的母串。下面的代码都可以去掉_copy,erase_first指的是删除第一次出现的,last指的是删除最后一次出现的,nth指的是删除第n次出现的,n从0开始,erase_head值的是删除前n个字符,erase_tail指的是删除后n个字符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include  <boost/algorithm/string.hpp>  #include  <iostream>  int  main ()    std::string s = "000111000111ababab000111000111" ;   std::cout << s << std::endl;      std::cout << boost::algorithm::erase_all_copy (s, "ab" ) << std::endl;   std::cout << boost::algorithm::erase_first_copy (s, "111" ) << std::endl;   std::cout << boost::algorithm::erase_last_copy (s, "111" ) << std::endl;   std::cout << boost::algorithm::erase_nth_copy (s, "111" ,0 ) << std::endl;   std::cout << boost::algorithm::erase_nth_copy (s, "111" ,100 ) << std::endl;   std::cout << boost::algorithm::erase_head_copy (s, 4 ) << std::endl;   std::cout << boost::algorithm::erase_tail_copy (s, 4 ) << std::endl; } 
查找子串  find一类的函数,同上,他将返回一个iterator_range的迭代器。这个迭代器可以操作子串。注意子串和母串共享空间。
1 2 3 4 5 6 7 8 9 10 11 #include  <boost/algorithm/string.hpp>  #include  <iostream>  int  main ()    std::string s = "000111000111ababab000111000111" ;   std::cout << s << std::endl;   auto  x = boost::algorithm::find_first (s,"000" );   x[0 ] = '2' ;   std::cout << s << std::endl;    } 
 又是一套代码下来了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include  <boost/algorithm/string.hpp>  #include  <iostream>  int  main ()    std::string s = "000111000111ababab000111000111" ;   std::cout << s << std::endl;   auto  x = boost::algorithm::find_first (s,"000" );   x = boost::algorithm::find_last (s,"1" );   x = boost::algorithm::find_nth (s,"1" ,3 );   x = boost::algorithm::find_tail (s,3 );   x = boost::algorithm::find_head (s,3 );   std::cout << s << std::endl;    } 
替换子串  replace又是一套如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include  <boost/algorithm/string.hpp>  #include  <iostream>  int  main ()    std::string s = "000111000111ababab000111000111" ;   std::cout << s << std::endl;      std::cout << boost::algorithm::replace_all_copy (s, "ab" ,"all" ) << std::endl;   std::cout << boost::algorithm::replace_first_copy (s, "111" ,"first" ) << std::endl;   std::cout << boost::algorithm::replace_last_copy (s, "111" ,"last" ) << std::endl;   std::cout << boost::algorithm::replace_nth_copy (s, "111" , 0 ,"nth" ) << std::endl;   std::cout << boost::algorithm::replace_nth_copy (s, "111" , 100 ,"nth" ) << std::endl;   std::cout << boost::algorithm::replace_head_copy (s, 2 ,"Head" ) << std::endl;   std::cout << boost::algorithm::replace_tail_copy (s, 2 ,"Tail" ) << std::endl; } 
修剪字符串  trim_left_copy 指的是从左边开始修建,删掉空字符等,trim_right_copy是从右边开始修建,trim_copy是两边一起修剪。
1 2 3 4 5 6 7 8 9 10 #include  <boost/algorithm/string.hpp>  #include  <iostream>  int  main ()    std::string s = "\t  ab  d d  d d d \t" ;   std::cout << "|"  << s << "|"  << std::endl;   std::cout << "|"  << boost::algorithm::trim_left_copy (s) << "|"  << std::endl;   std::cout << "|"  << boost::algorithm::trim_right_copy (s) << "|"  << std::endl;   std::cout << "|"  << boost::algorithm::trim_copy (s) << "|"  << std::endl; } 
 这个代码输出了
1 2 3 4 |      ab  d d  d d d     | |ab  d d  d d d     | |      ab  d d  d d d| |ab  d d  d d d| 
 我们还可以通过指定谓词来修剪使用trim_left_copy_if
1 2 3 4 5 6 7 8 9 10 #include  <boost/algorithm/string.hpp>  #include  <iostream>  int  main ()    std::string s = " 01 0 1 000ab  d d  d d d 11111111" ;   std::cout << "|"  << s << "|"  << std::endl;   std::cout << "|"  << boost::algorithm::trim_left_copy_if (s,boost::algorithm::is_any_of (" 01" )) << "|"  << std::endl;   std::cout << "|"  << boost::algorithm::trim_right_copy_if (s,boost::algorithm::is_any_of (" 01" )) << "|"  << std::endl;   std::cout << "|"  << boost::algorithm::trim_copy_if (s,boost::algorithm::is_any_of (" 01" )) << "|"  << std::endl; } 
 更多的谓词,我们还有is_lower、is_upper、is_space等谓词。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include  <boost/algorithm/string.hpp>  #include  <iostream>  int  main ()    std::string s = " 01 0 1 000ab  d d  d d d 11111111" ;   std::cout << "|"  << s << "|"  << std::endl;   std::cout << "|"  << boost::algorithm::trim_copy_if (s,boost::algorithm::is_space ()) << "|"  << std::endl;   std::cout << "|"  << boost::algorithm::trim_copy_if (s,boost::algorithm::is_digit ()) << "|"  << std::endl<<std::endl;   s = "aaaBBBaBBaaa" ;   std::cout << "|"  << s << "|"  << std::endl;   std::cout << "|"  << boost::algorithm::trim_copy_if (s,boost::algorithm::is_lower ()) << "|"  << std::endl; } 
字符串比较  starts_with(s,t)判断s是否以t开头,类似的有ends_with,contains,lexicographical_compare分别表示s是否以t结尾,s是否包含t,s与t的字典序比较。
1 2 3 4 5 6 7 8 9 10 11 #include  <boost/algorithm/string.hpp>  #include  <iostream>  int  main ()    std::cout << boost::algorithm::starts_with ("abcde" , "abc" ) << std::endl;   std::cout << boost::algorithm::ends_with ("abcde" , "cde" ) << std::endl;   std::cout << boost::algorithm::contains ("abcde" , "cde" ) << std::endl;   std::cout << boost::algorithm::lexicographical_compare ("abcde" , "cde" ) << std::endl;   std::cout << boost::algorithm::lexicographical_compare ("abcde" , "abcde" ) << std::endl;   std::cout << boost::algorithm::lexicographical_compare ("cde" , "abcde" ) << std::endl; } 
字符串分割  这个就简单多了,直接split+谓词函数就行了
1 2 3 4 5 6 7 8 9 10 #include  <boost/algorithm/string.hpp>  #include  <iostream>  int  main ()    std::string s = "abc abc abc * abc ( abc )" ;   std::vector<std::string> v;   boost::algorithm::split (v, s, boost::algorithm::is_any_of (" *()" ));   for  (auto  x : v) std::cout << x << "." ;   std::cout << std::endl; } 
输出
1 abc.abc.abc...abc...abc... 
我们注意看有些函数前面有个i,比如ierase_all, 这个说的是忽略大小写。
boost::regex  C++11的时候,被编入STL