boost assign

来源:互联网 发布:gltools王者荣耀优化 编辑:程序博客网 时间:2024/05/16 07:15

assign:
 许多情况下我们都需要为容器初始化或者赋值,填入大量的数据,比如初始错误代码和错误信息,或者是一些测试用的数据。STL容器仅提供了容纳这些数据的方法,但填充的步骤却是相当地麻烦,必须重复调用insert()或者push_back()等成员函数,这正是boost.assign出现的理由.
 assign库重载了赋值操作符,operator+=,逗号操作符operator,和括号操作符operator(),可以用难以想象的简洁语法非常方便地对STL容器赋值或者初始化,在需要填入大量初值的地方很有用。
#include <boost/assign.hpp>
using namespace boost::assign;

使用操作符 +=向容器增加元素
boost.assign,由于重载了操作符+=和逗号,可以用简洁到令人震惊的语法完成原来用许多代码才能完成的工作。
 使用assign库时必须使用using指示符,只有这样才能让重载的+=,等操作符在作用域内生效
示例:

#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <boost/assign.hpp>
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
using namespace boost;
using namespace std;
int main()
{
 using namespace boost::assign;//启用assign库的功能
 vector<int> v;    //标准向量容器
 v += 1, 2, 3, 4, 5, 6, 7*8;  //用operator+=和,填入数据
 set<string> s;    //标准集合容器
 s += "cpp", "java", "c#", "python";
 map<int, string> m;
 m += make_pair(1, "one"), make_pair(2, "two");
 system("pause");
 return 0;
}

 元素不一定是常量,表达式或者函数调用也是可以接受的,只要结果能够转换成容器可容纳的类型。比较特别的是map容器,必须用make_pair()辅助函数来生成容器元素,单纯地用括号把pair的两个成员括起来是无效的。
 operator+=很好用,但它仅应用与stl中定义的标准容器(vector,list,set等),对于其他类型的容器(如boost新容器)则无能为力.

使用操作符()向容器增加元素:
 operator+=使用上有些小的限制,而且在处理map容器也显麻烦,assign库使用操作符operator()提供更通用的解决方案。
 我们不能直接使用operator(),而应当使用assign库提供三个辅助函数insert(),push_front(),push_back().这些函数可作用于拥有同名成员函数的容器,接受容器变量作为参数,返回一个代理对象list_inserter,它重载了operator(),=等操作符用来实现向容器填入数据的功能。
示例:
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <boost/assign.hpp>
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
using namespace boost;
using namespace std;
int main()
{
 using namespace boost::assign;//启用assign库的功能
 vector<int> v;    //标准向量容器
 push_back(v)(1)(2)(3)(4); //使用push_back辅助函数
 list<string> l;
 push_front(l)("cpp")("java")("c#")("python"); //使用push_front辅助函数
 set<double> s;
 insert(s)(3.14)(3.15)(3.16)(3.17);    //使用insert辅助函数
 map<int, string> m;
 insert(m)(1, "one")(2, "two");
 system("pause");
 return 0;
}
 operator()的好处是可以在括号中使用多个参数,这对于map这样的元素是由多个值组成类型非常方便,避免了make_pair()函数的使用,而且,如果括号中没有参数,那么将调用容器元素的缺省构造函数填入一个缺省值,逗号操作符则不能这样做。
 括号操作符也可以与逗号等操作符配合使用,写法更简单:
 using namespace boost::assign;
 vector<int> v;
 push_back(v),1,2,3,4,5;
 push_back(v)(6),7,6,4,2;
 deque<string> d;
 push_front(d)() = "cpp","java","c#","python";
 assert(d.size() == 5);

初始化容器元素:
 操作符+=和()解决了对容器的赋值问题,但有的时候需要在容器构造的时候就完成数据的填充,这种方式较赋值更为高效。c++内建的数组和标准字符串类string支持这样做,但stl容器则不行。
 assign库使用list_of(),map_list_of()/pair_list_of()和tuple_list_of()三个函数解决了这个问题.

list_of:
 list_of()函数的用法与之前的insert(),push_back()等函数很相似,也重载了括号,逗号操作符。它很智能,返回一个匿名的列表,可以赋值给任意容器。
示例:
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <boost/assign.hpp>
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
using namespace boost;
using namespace std;
int main()
{
 using namespace boost::assign;//启用assign库的功能
 vector<int> v = list_of(1)(2)(3)(4)(5);
 deque<string> d = (list_of("power")("bomb"),("phazon"),("suit")); //注意括号的使用
 set<int> s = (list_of(10),20,30,50);
 map<int, string> m = list_of(make_pair(1, "one"))(make_pair(2, "two"));
 system("pause");
 return 0;
}

 list_of()函数可以全部使用括号操作符,也可以把括号与逗号结合起来,但使用后者时需要将整个list_of表达式用括号括起来,否则会使编译器无法推导出list_of的类型而无法赋值.

map_list_of/pair_list_of
 使用list_of()处理map容器不是很方便,于是map_list_of()/pair_list_of()应运而生,map_list_of()可以接受两个参数,然后自动构造std::pair对象插入map容器,pair_list_of()则纯粹是map_list_of的同义词,两者的用法功能完全相同.
#include <map>
#include <set>
#include <string>
#include <boost/assign.hpp>
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
using namespace boost;
using namespace std;
int main()
{
 using namespace boost::assign;//启用assign库的功能
 map<int, int> m1 = map_list_of(1, 2)(3, 4)(5, 6);
 map<int, string> m2 = map_list_of(1, "one")(2, "two");
 system("pause");
 return 0;
}

tuple_list_of:
 tuple_list_of用于初始化元素类型为tuple的容器,tuple是boost引入的一种新的容器/数据结构

减少重复输入:
 assign库提供repeat(),repeat_fun()和range()三个函数来减少重复的输入;
 repeat()函数把第二个参数作为要填入的值,重复第一个参数指定的次数,与vector,deque等容器的构造函数很相似,repeat_fun()函数同样重复第一个参数的次数,但第二个参数是个无参的函数或函数对象,它返回填入的数值;range()函数则可以把一个序列全部或部分元素插入到另一个序列里。

示例;
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <boost/assign.hpp>
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
#include <cstdlib>    //for rand()
using namespace boost;
using namespace std;
int main()
{
 using namespace boost::assign;//启用assign库的功能
 vector<int> v = list_of(1).repeat(3, 2)(3)(4)(5);
 // v = 1,2,2,2,3,4,5
 multiset<int> ms;
 insert(ms).repeat_fun(5, &rand).repeat(2, 1), 10;
 // ms = x,x,x,x,x,1,1,10
 deque<int> d;
 push_front(d).range(v.begin(), v.begin() + 5);
 // d = 3,2,2,2,1
 system("pause");
 return 0;
}

与非标准容器工作:
 assign库不仅支持全部八个STL标准容器(vector,string,deque,list,set,multiset,map,multimao),也对STL中的容器适配器提供了适当的支持,包括stack,queue和priority_queue.
 因为stack等容器适配器不符合容器的定义,没有insert,push_back等成员函数,所以不能使用赋值的方式填入元素,只能使用初始化的方式,并在list_of表达式最后使用to_adapter()成员函数来适配到非标准容器。如果使用逗号操作符还需要把整个表达式用括号括起来,才能使用点号调用to_adapter().
示例:
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <boost/assign.hpp>
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
#include <cstdlib>    //for rand()
using namespace boost;
using namespace std;
int main()
{
 using namespace boost::assign;
 stack<int> stk = (list_of(1), 2, 3).to_adapter();
 while(!stk.empty())//输出stack的内容
 {
  cout<<stk.top()<<" ";
  stk.pop();
 }
 cout<<endl;
 queue<string> q = (list_of("China")("US")("UK")).repeat(2, "russia").to_adapter();
 while(!q.empty())//输出queue的内容
 {
  cout<<q.front()<< " ";
  q.pop();
 }
 cout <<endl;
 priority_queue<double> pq = (list_of(1.414), 1.732, 2.236).to_adapter();
 while(!pq.empty())//输出优先队列的内容
 {
  cout<< pq.top()<< " ";
  pq.pop();
 }
 system("pause");
 return 0;
}
 assign库也支持部分不在STL中定义的非标准容器,如STLport中的slist和hash_set/hash_map。
示例:
#include <slist>    //非标准的单向链表
#include <hash_map>    //非标准的散列映射容器
#include <string>
#include <boost/assign.hpp>
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
#include <cstdlib>    //for rand()
using namespace boost;
using namespace std;
int main()
{
 using namespace boost::assign;
 //slist<int> sl;
 //push_front(sl), 1, 2, 3, 4, 5;
 hash_map<string, int> hm = map_list_of("one", 1)("two", 2);
 system("pause");
 return 0;
}
 此外,assign库还支持大部分Boost库容器,如array,circular_buffer,unordered等,用法同样与标准容器基本类似。

高级用法:
list_of()的嵌套使用
 list_of()可以就地创建匿名列表,它可与嵌套在assign库用法中,创建复杂的数据结构
使用vector构造一个二维数组,使用list_of(list_of)的嵌套形式来初始化:
using namespace boost::assign;
vector<vector<int>> v = list_of(list_of(1)(2)) (list_of(3)(4));
v += list_of(5)(6), list_of(7)(8);

引用初始化列表:
 在list_of之外assign库还有两个类似功能的ref_list_of()和cref_list_of(),这两个函数接受变量的引用作为参数来创建初始化匿名列表,较list_of()的效率更高,例如:
using namespace boost::assign;
int a = 1, b = 2, c = 3;
vector<int> v = ref_list_of<3>(a)(b)(c);
assert(v.size() == 3);

assign库还特别支持Boost中的指针容器,提供ptr_push_back(),ptr_list_of()等函数。

原创粉丝点击