boost库实用工具之assign

assign

  • 许多时候我们需要为容器初始化或者赋值,填入大量的数据时,用标准库中的容器填充步骤非常的麻烦,必须重复的使用insert或者push_back之类的成员函数。于是在boost中出现了assign.
  • assign库重载了赋值操作符operator += ,逗号操作符operator,和括号操作符 operator(), 我们可以用很简单的方法非常方便的对标准容器赋值或者初始化。在需要填充大量初始化值的时候非常方便。C++11标准也提供了类似的初始化工作,但是功能却没有assign库那么完备。
  • 使用assign库应包含头文件assign.hpp头文件

    #include <boost\assign.hpp>
    using namespace boost;

assign中的工具类

list_inserter

  • list_inserter是assign库中用来操作容器的工具类,它类似于std::back_inserter,但增加了很多操作符重载和助手类来简化代码。
  • 该工具类内部存储了一个函数对象insert_用来操作容器,这个函数对象包装了容器的push_back和push_front等操作。
  • list_inserter成员函数的另一个特点是返回*this指针,这使得它可以像标准流操作一样串联操作,达到简化代码的目的
list_inserter& operator,(const T& r) /// 重载 operator ,
{
    insert_(r);               /// 像容器添加元素
    return *this;             /// 返回自身的引用
}

operator+=

由于list_inserter重载了操作符+=和逗号,我们就可以让代码变得简洁
使用assign库时必须使用using指示符,这有这样才能让重载的+=,等操作符在作用域内生效
例如:

void assign_case1()
{
    using namespace boost::assign;

    std::vector<int> v;
    v += 1, 2, 3, 4, 5, 6 * 6;

    for (auto & x : v)
        cout << x << " ";
    cout << endl;

    std::set<string> s;
    s += "cpp", "java", "c#", "python";

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

    std::map<int, string> m;
    m += make_pair(1, "one"), make_pair(2, "two");

}

operator ()

  • operator += 只作用于容器,而且在处理map容器时就显得有些麻烦了,所以我们可以直接使用工厂函数 insert()/push_front()/push_back(),直接利用他们返回的list_inserter对象来填入数据。例如:
#include <forward_list>
void assign_case2()
{
    using namespace boost::assign;

    vector<int> v;
    push_back(v)(1)(2)(3)(4)(5);  /// 使用工厂函数

    list<string> l;
    push_front(l)("cpp")("java")("C#")("python");

    forward_list<string> f1;   /// C++11中向前的单向链表
    push_front(l)("matrix")("reload");

    set<double> s;
    insert(s)(3.14)(0.983)(1.175);

    map<int, string> m;
    insert(m)(1, "one")(2, "two");
}

generic_list

  • list_inserter解决的对容器的赋值问题,但有时候我们需要在容器构造的时候就完成数据的填充,这用方式赋值就比较高效。
    c++11标准库中引用了初始化列表std::initializer_list,而boost.assign库则提供了功能类似的generic_list,
  • generic_list与list_inserter类似,也重载了逗号和括号操作符,因为要在初始化时与容器互操作,它还额外增加了一些容器操作函数。
  • generic_list内部使用了std::deque存储元素,大多数操作都转换为deque的push_back()例如:
generic_list& operator ,(const T& u)
{
    this->push_back(u);
    return *this;
}

一个小的例子:

/ generic_list 构造的时候完成数据的填充
void assign_case3()
{
    using namespace boost::assign;

    vector<int> v;
    push_back(v), 1, 2, 3, 4, 5;
    push_back(v)(6), 7, 64 / 8, (9), 10;

    for (auto& x : v)
        cout << x << ",";
    cout << endl;

    deque<string> d;
    push_front(d)() = "cpp", "java", "c#", "python";
    assert(d.size() == 5);

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

初始化容器

assign 库提供的三个工厂函数 list_of , map_list_of/pair_list_of和tuple_list_of 它们能够产生generic_list 对象,然后我们就可以像list_inserter一样使用operator()和operator ,来填充数据。
因为 generic_list 提供到容器类型的隐式转型操作,所以他可以赋值给任意容器,当然我们也可以显示调用显示转换函数

// 初始化列表
/// 3个工厂函数 list_of, map_list_of/pair_list_of和tuple_list_of.
void assign_case4()
{
    using namespace boost::assign;

    vector<int> v = list_of(1)(2)(3)(4)(5);
    // v = [1,2,3,4,5]

    deque<string> d = (list_of("power")("bomb"), "phazon", "suit");
    // d = [power bomb phazon suit]

    set<int> s = (list_of(10), 20, 30, 40, 50);
    // s = {10 20 30 40 50}

    map<int, string> m = list_of(make_pair(1, "one"))(make_pair(2, "two"));
    // m = [(1, “one”) (2, “two”)]

    map<int, int> m1 = map_list_of(1, 2)(3, 4)(5, 6);
    //m1 = [(1, 2)(3, 4)(5, 6)]

    map<int,string> m2= map_list_of(1, "one")(2, "two");
    //m2 = [(1, "one")(2, "two")]
}

减少重复输入

在填充数据时会遇到重复数据输入的问题,如果用之前的方法就要写较多的代码,我们可以用list_inserter 和 generic_list 都提供了成员函数repeat(), repeat_fun() 和 range()来进去工作量。这三个函数简要申明如下:
list& repeat(std::size_t sz, U u);
list& repeat_fu(std::size_t sz, Nullary_function fun);
list& range(SinglePassIterator first, SinglePassIterator last);
简单的例子使用:

#include <cstdlib>
/// 减少重复输入
void assign_case5()
{
    using namespace boost::assign;

    vector<int> v = list_of(1).repeat(3, 2)(3)(4)(5);
    //v = 1,2,2,2,3,4,5
    for (auto& x : v)
        cout << x << ",";
    cout << endl;

    multiset<int> ms;
    insert(ms).repeat_fun(5, &rand).repeat(2, 1), 10;
    //ms = x,x,x,x,x,1,1,10
    for (auto& x : ms)
        cout << x << ",";
    cout << endl;

    deque<int> d;
    push_front(d).range(v.begin(), v.begin() + 5);
    //d = 3,2,2,2,1
    for (auto& x : d)
        cout << x << ",";
    cout << endl;
}

操作非标准容器

assign 库不仅支持全部8 个标准容器(vector, string, deque, list, set, multiset, map, multimap),也对容器适配器提供了适当的支持,包括stack, queue, priority_queue

#include <stack>
#include <queue>
void assign_case6()
{
    using namespace boost::assign;

    stack<int> stk = (list_of(1), 2, 3).to_adapter();

    stk += 4, 5, 6;
    for (; !stk.empty();)
    {
        cout << stk.top() << " ";
        stk.pop();
    }
    cout << endl;

    queue<string> q = (list_of("china")("us")("uk")).
        repeat(2, "russia").to_adapter();
    push(q)("germany");
    for (; !q.empty();)
    {
        cout << q.front() << " ";
        q.pop();
    }
    cout << endl;

    priority_queue<double> pq = (list_of(1.414), 1.732, 2.236).to_adapter();
    push(pq), 3.414, 2.71828;
    for (; !pq.empty();)
    {
        cout << pq.top() << " ";
        pq.pop();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值