Boost库中boost::assign的使用
一、boost::assign 概述
头文件:
#include <boost/assign.hpp>
using namespace boost::assign;
作用:
提供一组便捷函数和运算符重载,使 STL 容器的初始化、填充、链式构造更直观。
二、基本用法:容器初始化与链式赋值
1. 向量初始化
#include <boost/assign.hpp>
#include <vector>
#include <iostream>
using namespace boost::assign;int main() {std::vector<int> v = list_of(1)(2)(3)(4)(5);for (int x : v)std::cout << x << " ";
}
输出:
1 2 3 4 5
解释:
list_of(1)创建一个临时构造器对象;- 每次
(2)(3)调用重载的operator(),将新元素追加; - 最终隐式转换为
std::vector<int>。
2. 列表扩展 (list_of().range())
可以从已有容器中导入:
std::vector<int> base = {1,2,3};
std::vector<int> v = list_of(0).range(base.begin(), base.end())(4);
结果:
v = [0, 1, 2, 3, 4]
3. += 风格赋值
适用于已存在的容器:
std::vector<std::string> names;
names += "Alice", "Bob", "Charlie";
相当于:
names.push_back("Alice");
names.push_back("Bob");
names.push_back("Charlie");
4. 关联容器(map, set)
Map 示例:
std::map<std::string, int> ages = map_list_of("Alice", 20)("Bob", 22)("Charlie", 19);
相当于:
ages["Alice"] = 20;
ages["Bob"] = 22;
ages["Charlie"] = 19;
Set 示例:
std::set<int> s = list_of(1)(2)(3)(5);
三、各种 assign 工具函数一览
| 函数名 | 用途 | 支持容器类型 | 说明 |
|---|---|---|---|
list_of() | 初始化序列式容器 | vector, deque, list, set | 生成一个链式赋值器 |
map_list_of() | 初始化 map / multimap | map, multimap | 用键值对赋值 |
set_list_of() | 初始化 set / multiset | set, multiset | 元素递增添加 |
tuple_list_of() | 初始化 pair / tuple 容器 | vector, list | 用于多元结构 |
operator+= | 连续向容器 push_back | vector, list, deque | 类似 Python 的 extend |
push_back() | 为已有容器生成链式 push 接口 | vector, list, deque | 见下方例子 |
insert() | 为 set/map 提供链式 insert | set, map, multimap |
四、链式 push_back / insert 用法详解
push_back 用法
std::vector<int> v;
push_back(v)(1)(2)(3)(4);
等价于:
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
insert 用法
std::set<std::string> s;
insert(s)("apple")("banana")("cherry");
或者:
std::map<int, std::string> m;
insert(m)(1, "one")(2, "two")(3, "three");
五、组合示例
#include <boost/assign.hpp>
#include <map>
#include <vector>
#include <set>
#include <iostream>
using namespace boost::assign;int main() {// 1. vector 初始化std::vector<int> v = list_of(1)(2)(3)(5);// 2. set 初始化std::set<std::string> s = list_of("apple")("banana")("cherry");// 3. map 初始化std::map<int, std::string> m = map_list_of(1, "one")(2, "two")(3, "three");// 4. 已有容器的连续添加push_back(v)(6)(7)(8);insert(s)("pear")("mango");insert(m)(4, "four")(5, "five");// 输出for (auto x : v) std::cout << x << " ";std::cout << "\n";for (auto &p : m) std::cout << p.first << ":" << p.second << " ";
}
六、内部机制
boost::assign 基于模板类 list_inserter、map_list_of 实现,利用了:
- 模板偏特化 来区分容器类型;
- operator() 链式调用 将连续元素插入;
- 隐式类型转换操作符 将 builder 对象转换成容器;
- 返回引用自身 (
*this) 实现链式语法; - 重载 operator, (逗号) 支持
+=风格。
例如:
template<class Container>
class list_inserter {Container c_;
public:list_inserter(const typename Container::value_type& v) { c_.push_back(v); }list_inserter& operator()(const typename Container::value_type& v) {c_.push_back(v);return *this;}operator Container() const { return c_; }
};
️ 七、注意事项与常见坑
| 问题 | 说明 |
|---|---|
| ① 链式赋值对象是临时的 | 一定要用 list_of(...) 初始化,而不是用 = 之后再加 (x)。 |
② += 方式要求容器已存在 | 否则编译错误。 |
| ③ 性能:不是零开销 | 每次调用都会触发 push_back() 或 insert()。 |
④ 不能用于 std::array | 因为它是固定长度。 |
| ⑤ C++11 之后可用列表初始化替代 | 但 Boost.Assign 更灵活(支持 map, range, 连续追加等)。 |
八、与 C++11 初始化列表的比较
| 功能 | Boost.Assign | C++11 初始化列表 |
|---|---|---|
| 适用于 pre-C++11 | ✅ | ❌ |
| 可用于 map 链式构造 | ✅ | ⭕️(语法更啰嗦) |
| 可逐步扩展容器 | ✅ | ❌ |
可与已有容器 += | ✅ | ❌ |
| 支持 range 扩展 | ✅ | ❌ |
九、小结
| 功能类别 | Boost.Assign 用法 | 对应 STL 操作 |
|---|---|---|
| 初始化 vector | list_of(1)(2)(3) | push_back 多次 |
| 初始化 map | map_list_of("A",1)("B",2) | insert 多次 |
| 已有容器追加 | container += a, b, c; | push_back |
| 批量添加 | push_back(v)(1)(2)(3) | push_back |
| 插入到 set/map | insert(s)("x")("y") | insert |
