C++ boost::range 详解:基于最新版本的现代范围处理指南
- [一、C++ boost::range 详解](#一、C++ boost::range 详解)
-
- [1. 引言:为什么需要 boost::range?](#1. 引言:为什么需要 boost::range?)
- [2、boost::range 核心概念](#2、boost::range 核心概念)
-
- [2.1、 什么是 Range?](#2.1、 什么是 Range?)
- [2.2、 Range 适配器与算法](#2.2、 Range 适配器与算法)
- 3、安装与配置(基于最新版本)
- [4、基础用法:从 STL 算法到 Range 算法](#4、基础用法:从 STL 算法到 Range 算法)
-
- [4.1 、直接替换 STL 算法](#4.1 、直接替换 STL 算法)
- [4.2、 处理子范围](#4.2、 处理子范围)
- [5、高级特性:Range 适配器](#5、高级特性:Range 适配器)
-
- [5.1、 过滤(filtered)](#5.1、 过滤(filtered))
- [5.2、 变换(transformed)](#5.2、 变换(transformed))
- [5.3、 其他常用适配器](#5.3、 其他常用适配器)
- [6、 实用工具函数](#6、 实用工具函数)
-
- [6.1、 范围生成器](#6.1、 范围生成器)
- [6.2 、连接多个范围](#6.2 、连接多个范围)
- [6.3 、判断范围属性](#6.3 、判断范围属性)
- 7、性能考虑与最佳实践
-
- [7.1、 惰性求值的优势](#7.1、 惰性求值的优势)
- [7.2、 何时复制 vs 何时使用视图](#7.2、 何时复制 vs 何时使用视图)
- [7.3 、与 C++20 Ranges 的兼容性](#7.3 、与 C++20 Ranges 的兼容性)
- [8、 实战示例:数据处理管道](#8、 实战示例:数据处理管道)
- 9、总结
-
- [9.1 、主要优势](#9.1 、主要优势)
- [9.2、 适用场景](#9.2、 适用场景)
- 二、代码示例

一、C++ boost::range 详解
1. 引言:为什么需要 boost::range?
在传统的 C++ STL 算法中,我们经常需要传递一对迭代器(begin/end)来指定操作范围:
cpp
std::vector<int> vec = {1, 2, 3, 4, 5};
std::sort(vec.begin(), vec.end()); // 传统方式
这种方式虽然灵活,但存在几个明显问题:
- 代码冗长 :每次都要写
begin()和end() - 容易出错:begin/end 不匹配可能导致未定义行为
- 缺乏组合性:难以将多个算法操作流畅地串联起来
boost::range 库正是为了解决这些问题而生。它提供了一种**范围(Range)**的抽象,将一对迭代器封装为单个对象,让代码更简洁、更安全、更具表现力。
2、boost::range 核心概念
2.1、 什么是 Range?
在 boost::range 中,一个 Range 就是任何可以获取到 begin() 和 end() 迭代器的对象。这包括:
- 所有 STL 容器(vector、list、map、set 等)
- 原生数组
- 字符串(std::string、C 风格字符串)
- 迭代器对(std::pair<iterator, iterator>)
- 以及任何自定义的满足 Range 概念的类型
2.2、 Range 适配器与算法
boost::range 提供了两大核心组件:
- Range 算法:STL 算法的 Range 版本,接受 Range 对象而非迭代器对
- Range 适配器:对现有 Range 进行变换,生成新的"视图"Range
3、安装与配置(基于最新版本)
3.1、下载库


3.2、Visual Studio新建工程

3. 3、将源码解压到工程目录下
新建一个main.cpp文件

将下载的压缩包解压到main.cpp同级目录,并改名为boost

3.4、添加路径




4、基础用法:从 STL 算法到 Range 算法
4.1 、直接替换 STL 算法
几乎所有 STL 算法都有对应的 boost::range 版本:
cpp
#include <vector>
#include <iostream>
#include <boost/range/algorithm.hpp>
int main() {
std::vector<int> numbers = {5, 2, 8, 1, 9, 3};
// 传统 STL 方式
std::sort(numbers.begin(), numbers.end());
// boost::range 方式(更简洁)
boost::sort(numbers);
// 其他常用算法
auto it = boost::find(numbers, 8); // 查找元素
bool has_three = boost::contains(numbers, 3); // 检查包含
boost::reverse(numbers); // 反转
// 输出结果
boost::copy(numbers, std::ostream_iterator<int>(std::cout, " "));
// 输出: 1 2 3 5 8 9
return 0;
}
4.2、 处理子范围
cpp
#include <boost/range/algorithm.hpp>
#include <boost/range/sub_range.hpp>
std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 创建子范围(不复制数据)
auto sub = boost::make_iterator_range(vec.begin() + 2, vec.begin() + 7);
// sub 包含: {3, 4, 5, 6, 7}
// 对子范围排序
boost::sort(sub);
// 原 vec 变为: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// 查找子范围中的元素
auto pos = boost::find(sub, 5); // 返回指向 vec[4] 的迭代器
5、高级特性:Range 适配器
Range 适配器是 boost::range 最强大的功能之一,它们可以惰性地转换 Range,而不立即复制或计算所有元素。
5.1、 过滤(filtered)
cpp
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm/copy.hpp>
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 过滤出偶数
auto even_numbers = numbers | boost::adaptors::filtered([](int n) {
return n % 2 == 0;
});
// 惰性求值:此时尚未计算
std::cout << "偶数: ";
boost::copy(even_numbers, std::ostream_iterator<int>(std::cout, " "));
// 输出: 2 4 6 8 10
5.2、 变换(transformed)
cpp
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <cmath>
std::vector<int> values = {1, 2, 3, 4, 5};
// 计算平方
auto squares = values | boost::adaptors::transformed([](int x) {
return x * x;
});
std::cout << "平方: ";
boost::copy(squares, std::ostream_iterator<int>(std::cout, " "));
// 输出: 1 4 9 16 25
// 链式调用:先过滤再变换
auto result = values
| boost::adaptors::filtered([](int x) { return x > 2; })
| boost::adaptors::transformed([](int x) { return std::sqrt(x); });
5.3、 其他常用适配器
cpp
#include <boost/range/adaptors.hpp>
std::vector<std::pair<int, std::string>> pairs = {
{1, "one"}, {2, "two"}, {3, "three"}
};
// 1. 取键(keys)
auto keys = pairs | boost::adaptors::map_keys;
// 包含: {1, 2, 3}
// 2. 取值(values)
auto values = pairs | boost::adaptors::map_values;
// 包含: {"one", "two", "three"}
// 3. 反转(reversed)
std::vector<int> vec = {1, 2, 3};
auto reversed = vec | boost::adaptors::reversed;
// 包含: {3, 2, 1}
// 4. 唯一化(uniqued)
std::vector<int> dup = {1, 2, 2, 3, 3, 3};
auto unique = dup | boost::adaptors::uniqued;
// 包含: {1, 2, 3}
// 5. 切片(sliced)
std::vector<int> nums = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
auto slice = nums | boost::adaptors::sliced(2, 7);
// 包含索引 [2, 7) 的元素: {2, 3, 4, 5, 6}
6、 实用工具函数
6.1、 范围生成器
cpp
#include <boost/range/irange.hpp>
#include <boost/range/algorithm/copy.hpp>
// 生成整数范围 [0, 10)
auto range1 = boost::irange(0, 10);
// 包含: 0, 1, 2, ..., 9
// 指定步长 [0, 20),步长为 3
auto range2 = boost::irange(0, 20, 3);
// 包含: 0, 3, 6, 9, 12, 15, 18
// 生成递减范围 [10, 0),步长为 -2
auto range3 = boost::irange(10, 0, -2);
// 包含: 10, 8, 6, 4, 2
6.2 、连接多个范围
cpp
#include <boost/range/join.hpp>
#include <boost/range/algorithm/copy.hpp>
std::vector<int> vec1 = {1, 2, 3};
std::list<int> vec2 = {4, 5, 6};
std::array<int, 3> vec3 = {7, 8, 9};
// 连接不同类型的容器
auto combined = boost::join(boost::join(vec1, vec2), vec3);
std::cout << "连接结果: ";
boost::copy(combined, std::ostream_iterator<int>(std::cout, " "));
// 输出: 1 2 3 4 5 6 7 8 9
6.3 、判断范围属性
cpp
#include <boost/range/algorithm.hpp>
#include <boost/range/size.hpp>
#include <boost/range/empty.hpp>
#include <boost/range/distance.hpp>
std::vector<int> vec = {1, 2, 3, 4, 5};
// 获取范围大小
std::size_t sz = boost::size(vec); // 5
std::ptrdiff_t dist = boost::distance(vec); // 5
// 检查是否为空
bool is_empty = boost::empty(vec); // false
// 检查是否已排序
bool is_sorted = boost::is_sorted(vec); // true(如果已排序)
// 查找极值
auto min_it = boost::min_element(vec); // 指向 1
auto max_it = boost::max_element(vec); // 指向 5
7、性能考虑与最佳实践
7.1、 惰性求值的优势
Range 适配器采用惰性求值,这意味着:
cpp
// 示例:处理大量数据
std::vector<int> big_data(1000000);
std::iota(big_data.begin(), big_data.end(), 0);
// 传统方式(立即计算,内存占用高)
std::vector<int> temp;
std::copy_if(big_data.begin(), big_data.end(),
std::back_inserter(temp),
[](int x) { return x % 2 == 0; });
std::transform(temp.begin(), temp.end(), temp.begin(),
[](int x) { return x * 2; });
// Range 方式(惰性计算,内存友好)
auto result = big_data
| boost::adaptors::filtered([](int x) { return x % 2 == 0; })
| boost::adaptors::transformed([](int x) { return x * 2; });
// 只有在实际使用时才计算
int sum = 0;
for (int x : result | boost::adaptors::sliced(0, 100)) {
sum += x; // 只计算前100个元素
}
7.2、 何时复制 vs 何时使用视图
cpp
// 情况1:需要修改原数据 → 使用算法
std::vector<int> data = {3, 1, 4, 1, 5};
boost::sort(data); // 直接修改原容器
// 情况2:只需要读取或临时处理 → 使用适配器(视图)
auto even_view = data | boost::adaptors::filtered([](int x) {
return x % 2 == 0;
}); // 不复制数据
// 情况3:需要持久化结果 → 复制到新容器
std::vector<int> even_numbers;
boost::copy(even_view, std::back_inserter(even_numbers));
7.3 、与 C++20 Ranges 的兼容性
如果你正在使用 C++20 或更新版本,可以考虑迁移到标准库的 <ranges>:
cpp
// C++20 标准 Ranges(对比 boost::range)
#include <ranges>
#include <algorithm>
std::vector<int> vec = {1, 2, 3, 4, 5};
// boost::range 方式
auto boost_result = vec
| boost::adaptors::filtered([](int x) { return x % 2 == 0; })
| boost::adaptors::transformed([](int x) { return x * x; });
// C++20 Ranges 方式
auto std_result = vec
| std::views::filter([](int x) { return x % 2 == 0; })
| std::views::transform([](int x) { return x * x; });
迁移建议:
- 新项目优先使用 C++20
<ranges> - 现有使用
boost::range的项目可逐步迁移 boost::range在 C++11/14/17 项目中仍是优秀选择
8、 实战示例:数据处理管道
让我们通过一个完整的例子展示 boost::range 在实际项目中的应用:
cpp
#include <iostream>
#include <vector>
#include <string>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/irange.hpp>
struct Person {
std::string name;
int age;
double salary;
};
int main() {
std::vector<Person> employees = {
{"Alice", 25, 50000.0},
{"Bob", 30, 60000.0},
{"Charlie", 35, 75000.0},
{"David", 28, 55000.0},
{"Eve", 40, 80000.0}
};
// 任务:找出年龄在30-40岁之间,薪资超过60000的员工名字
auto result = employees
| boost::adaptors::filtered([](const Person& p) {
return p.age >= 30 && p.age <= 40;
})
| boost::adaptors::filtered([](const Person& p) {
return p.salary > 60000.0;
})
| boost::adaptors::transformed([](const Person& p) {
return p.name;
});
std::cout << "符合条件的员工: ";
boost::copy(result, std::ostream_iterator<std::string>(std::cout, ", "));
// 输出: Charlie, Eve,
// 额外:计算平均薪资
auto salaries = employees | boost::adaptors::transformed(
[](const Person& p) { return p.salary; }
);
double total = 0.0;
for (double s : salaries) {
total += s;
}
double average = total / boost::size(employees);
std::cout << "\n平均薪资: " << average << std::endl;
return 0;
}

9、总结
boost::range 为 C++ 开发者提供了以下核心价值:
9.1 、主要优势
- 代码简洁性 :消除冗余的
begin()/end()调用 - 安全性提升:减少迭代器不匹配的错误
- 表现力增强:支持流畅的函数式编程风格
- 性能优化:惰性求值减少不必要的计算和内存分配
- 兼容性好:支持 C++11 及以后版本,与 STL 无缝集成
9.2、 适用场景
- 数据处理管道和转换
- 算法链式调用
- 大型数据集的惰性处理
- 需要代码简洁性的项目
- 准备向 C++20 Ranges 迁移的代码库
二、代码示例
1、示例代码
cpp
#include <iostream>
#include <vector>
#include <tuple>
#include <boost/range.hpp>
#include <boost/range/irange.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/numeric.hpp>
// 简写命名空间,代码更清爽
namespace br = boost::range;
namespace ba = boost::adaptors;
// 打印工具
template<typename Range>
void print(const std::string& label, const Range& r)
{
std::cout << label << ": ";
for (auto v : r)
std::cout << v << " ";
std::cout << "\n";
}
int main()
{
std::vector<int> data = { 1,2,3,4,5,6,7,8,9,10 };
// 1. 生成数值区间
auto nums = boost::irange(1, 11);
print("irange 1~10", nums);
// 2. 反转
auto rev = data | ba::reversed;
print("反转", rev);
// 3. 过滤:只保留偶数
auto even = data | ba::filtered([](int x) { return x % 2 == 0; });
print("只保留偶数", even);
// 4. 转换:全部平方
auto square = data | ba::transformed([](int x) { return x * x; });
print("全部平方", square);
// 5. 链式组合:过滤偶数 + 平方 + 反转
auto pipe = data
| ba::filtered([](int x) { return x % 2 == 0; })
| ba::transformed([](int x) { return x * x; })
| ba::reversed;
print("链式流水线", pipe);
// 6. 切片 [2,6)
auto slice = data | ba::sliced(2, 6);
print("切片2~6", slice);
// 7. 带下标遍历
std::cout << "带下标遍历: ";
for (auto item : data | ba::indexed(0))
{
std::cout << "(" << item.index() << "," << item.value() << ") ";
}
std::cout << "\n";
// 8. range求和
int sum = std::accumulate(boost::begin(data), boost::end(data), 0);
std::cout << "数组总和 = " << sum << "\n";
// 9.判断是否包含元素(不用contains)
auto find_it = boost::find(data, 5);
bool exist = (find_it != boost::end(data));
std::cout << "是否包含5: " << std::boolalpha << exist << "\n";
//10. range转vector(boost::begin/end)
auto filter_view = data | ba::filtered([](int x) { return x > 5; });
std::vector<int> res(boost::begin(filter_view), boost::end(filter_view));
print("视图转vector", res);
return 0;
}
2、运行结果
cpp
irange 1~10: 1 2 3 4 5 6 7 8 9 10
反转: 10 9 8 7 6 5 4 3 2 1
只保留偶数: 2 4 6 8 10
全部平方: 1 4 9 16 25 36 49 64 81 100
链式流水线: 100 64 36 16 4
切片2~6: 3 4 5 6
带下标遍历: (0,1) (1,2) (2,3) (3,4) (4,5) (5,6) (6,7) (7,8) (8,9) (9,10)
数组总和 = 55
是否包含5: true
视图转vector: 6 7 8 9 10
D:\user\01417804\桌面\新建文件夹\Project1\x64\Debug\Project1.exe (进程 24260)已退出,代码为 0 (0x0)。
要在调试停止时自动关闭控制台,请启用"工具"->"选项"->"调试"->"调试停止时自动关闭控制台"。
按任意键关闭此窗口. . .

