相关章节: 循环迭代器 | 属性映射 | 半边数据结构 | 组合地图
3.1 CGAL的STL扩展
1. 理论基础
1.1 范围概念(Range)的数学理论
在计算几何算法中,**范围(Range)**是一个核心抽象概念。从数学角度看,范围可以定义为一个有序对 ,其中 是起始迭代器, 是终止迭代器,表示半开区间 。
CGAL的范围概念扩展了STL的迭代器范围,提供了以下数学性质:
定义 1.1(范围):设 为迭代器类型,范围 是满足以下条件的有序对:
- ,返回起始迭代器
- ,返回终止迭代器
- , 可通过解引用访问
定义 1.2(范围类别):
- Forward_range: 支持前向遍历,满足 操作
- Bidirectional_range: 支持双向遍历,满足 和 操作
- Random_access_range: 支持随机访问,满足 和 操作
1.2 与C++20 Ranges的对比
| 特性 | CGAL Iterator_range | C++20 std::ranges |
|---|---|---|
| 标准符合性 | C++11/14/17兼容 | 需要C++20 |
| 概念定义 | 基于Boost.Range | 原生语言支持 |
| 惰性求值 | 不支持 | 支持views |
| 管道操作 | 不支持 | 支持 |> 操作符 |
| Borrowed range | C++20特化支持 | 原生支持 |
CGAL的Iterator_range设计目标是与Boost.Range和STL算法兼容,同时保持对旧版本C++标准的支持。在C++20环境下,CGAL提供了std::ranges::enable_borrowed_range特化,使得Iterator_range可以与C++20 ranges库无缝协作。
1.3 迭代器适配器的设计模式
迭代器适配器是**适配器模式(Adapter Pattern)**的典型应用,它允许在不修改原始迭代器的情况下,改变其行为或接口。
设计原则:
- 单一职责原则:每个适配器只负责一种转换
- 开闭原则:对扩展开放,对修改封闭
- 最小惊讶原则:适配器的行为应符合用户预期
2. 架构分析
2.1 Iterator_range类层次结构
std::pair<I, I>
↑
Iterator_range<I>
├── begin() / end()
├── size()
├── empty()
├── operator std::tuple<I&, I&>
├── operator std::tuple<const I&, const I&>
└── to<Container>() // C++17模板模板参数
Iterator_range继承自std::pair<I, I>,这使得它可以与boost::tie一起使用,方便地解包范围。
2.2 迭代器适配器体系
CGAL提供了多种迭代器适配器:
| 适配器 | 功能描述 | 迭代器类别支持 |
|---|---|---|
Iterator_transform<I, Fct> | 遍历时应用函数变换 | 全类别 |
Filter_iterator<I, P> | 条件过滤元素 | 前向/双向/随机访问 |
Counting_iterator<I> | 带计数的迭代器 | 输入迭代器 |
N_step_adaptor<I, N> | 每次前进N步 | 全类别 |
Prevent_deref<I> | 阻止解引用 | 全类别 |
2.3 概念定义(Concepts)
CGAL使用Boost.ConceptCheck和C++20 concepts(如果可用)来定义迭代器概念:
// ForwardRange概念
template<typename R>
concept ForwardRange = requires(R r) {
{ r.begin() } -> std::forward_iterator;
{ r.end() } -> std::forward_iterator;
};
// CGAL特定的范围概念
template<typename R>
concept CGAL_Range = requires(R r) {
{ *r.begin() } -> std::convertible_to<std::iter_value_t<decltype(r.begin())>>;
{ r.begin() != r.end() } -> std::convertible_to<bool>;
};3. 实现细节
3.1 Iterator_range完整实现
// 文件: CGAL/Iterator_range.h
namespace CGAL {
/*!
\ingroup PkgSTLExtensionRef
`CGAL::Iterator_range` encapsulates two iterators so they fulfill the `ForwardRange` concept.
The class is essentially a clone of boost::iterator_range,
and it additionally is derived from `std::pair`, so that one can apply `boost::tie`.
*/
template <typename I>
class Iterator_range : public std::pair<I, I>
{
typedef std::pair<I, I> Base;
public:
typedef I iterator;
typedef I const_iterator;
// 默认构造函数
Iterator_range() = default;
// 从迭代器对构造
Iterator_range(I b, I e) : Base(b, e) {}
// 从std::pair构造
Iterator_range(const std::pair<I, I>& ip) : Base(ip) {}
// 范围访问
I begin() const { return this->first; }
I end() const { return this->second; }
// 返回std::distance(begin(), end())
std::size_t size() const {
return static_cast<std::size_t>(std::distance(begin(), end()));
}
// 返回size() == 0
bool empty() const { return begin() == end(); }
// 转换为tuple,支持结构化绑定
operator std::tuple<I&, I&>() {
return std::tuple<I&, I&>{this->first, this->second};
}
operator std::tuple<const I&, const I&>() const {
return std::tuple<const I&, const I&>{this->first, this->second};
}
// 转换为指定容器类型(C++17)
template <template<class...> class Container>
auto to() const {
using V = std::remove_cv_t<std::remove_reference_t<decltype(*begin())>>;
return Container<V>(begin(), end());
}
};
// 工厂函数
template <typename T>
Iterator_range<T> make_range(const T& b, const T& e) {
return Iterator_range<T>(b, e);
}
template <typename T>
Iterator_range<T> make_range(const std::pair<T, T>& p) {
return Iterator_range<T>(p.first, p.second);
}
} // namespace CGAL
// C++20支持:声明为borrowed_range
#if CGAL_CXX20 && __cpp_lib_ranges >= 201911L
#include <ranges>
template<typename I>
inline constexpr bool std::ranges::enable_borrowed_range<CGAL::Iterator_range<I>> = true;
#endif3.2 Transform_iterator实现
// 文件: CGAL/Iterator_transform.h
namespace CGAL {
template <class I, class Fct>
class Iterator_transform {
protected:
I nt; // 内部迭代器
public:
typedef Iterator_transform<I, Fct> Self;
typedef I Iterator;
typedef std::iterator_traits<I> traits;
typedef typename traits::difference_type difference_type;
typedef typename traits::iterator_category iterator_category;
typedef typename traits::value_type base_value_type;
typedef typename traits::pointer base_pointer;
typedef typename traits::reference base_reference;
typedef typename Fct::argument_type argument_type;
typedef typename Fct::result_type value_type;
// 重要:返回rvalue,允许转换函数返回新对象
typedef value_type reference;
// 构造函数
Iterator_transform() {}
Iterator_transform(I j) : nt(j) {}
// 类型转换构造函数
template <class I2>
Iterator_transform(const Iterator_transform<I2, Fct>& i2)
: nt(i2.current_iterator()) {}
// 前向迭代器操作
Iterator current_iterator() const { return nt; }
bool operator==(const Self& i) const { return nt == i.nt; }
bool operator!=(const Self& i) const { return !(*this == i); }
// Proxy类支持operator->
struct Proxy {
Proxy(const reference r) : ref(r) {}
reference ref;
pointer operator->() { return &ref; }
};
Proxy operator->() const {
return Proxy(Fct()(*nt));
}
reference operator*() const {
Fct fct;
return fct(*nt);
}
Self& operator++() {
++nt;
return *this;
}
Self operator++(int) {
Self tmp = *this;
++*this;
return tmp;
}
// 双向迭代器操作
Self& operator--() {
--nt;
return *this;
}
Self operator--(int) {
Self tmp = *this;
--*this;
return tmp;
}
// 随机访问迭代器操作
Self& operator+=(difference_type n) {
nt += n;
return *this;
}
Self operator+(difference_type n) const {
Self tmp = *this;
return tmp += n;
}
Self& operator-=(difference_type n) {
return operator+=(-n);
}
Self operator-(difference_type n) const {
Self tmp = *this;
return tmp += -n;
}
difference_type operator-(const Self& i) const {
return nt - i.nt;
}
reference operator[](difference_type n) const {
Self tmp = *this;
tmp += n;
return tmp.operator*();
}
bool operator<(const Self& i) const { return nt < i.nt; }
bool operator>(const Self& i) const { return i < *this; }
bool operator<=(const Self& i) const { return !(i < *this); }
bool operator>=(const Self& i) const { !(*this < i); }
};
} // namespace CGAL3.3 Filter_iterator实现
// 文件: CGAL/iterator.h
template <class I, class P>
class Filter_iterator {
typedef I Iterator;
typedef P Predicate;
typedef Filter_iterator<I, P> Self;
typedef std::iterator_traits<I> ITI;
typedef typename ITI::reference reference;
typedef typename ITI::pointer pointer;
typedef typename ITI::value_type value_type;
typedef typename ITI::difference_type difference_type;
typedef typename ITI::iterator_category iterator_category;
protected:
Iterator e_; // 终止位置
Iterator c_; // 当前位置
Predicate p_; // 谓词:p_(x)为true时跳过x
public:
Filter_iterator() {}
// 构造空过滤器
Filter_iterator(Iterator e, const Predicate& p)
: e_(e), c_(e), p_(p) {}
// 构造并定位到第一个非过滤元素
Filter_iterator(Iterator e, const Predicate& p, Iterator c)
: e_(e), c_(c), p_(p) {
while (c_ != e_ && p_(c_))
++c_;
}
// 前向迭代
Self& operator++() {
do { ++c_; } while (c_ != e_ && p_(c_));
return *this;
}
// 双向迭代(仅当底层迭代器支持时)
Self& operator--() {
do { --c_; } while (p_(c_));
return *this;
}
reference operator*() const { return *c_; }
pointer operator->() const { return &*c_; }
const Predicate& predicate() const { return p_; }
const Iterator& base() const { return c_; }
Iterator end() const { return e_; }
bool is_end() const { return (c_ == e_); }
};
// 工厂函数
template <class I, class P>
inline Filter_iterator<I, P> filter_iterator(I e, const P& p) {
return Filter_iterator<I, P>(e, p);
}
template <class I, class P>
inline Filter_iterator<I, P> filter_iterator(I e, const P& p, I c) {
return Filter_iterator<I, P>(e, p, c);
}4. 使用示例
4.1 示例1:基本Iterator_range使用
#include <CGAL/Iterator_range.h>
#include <CGAL/iterator.h>
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
// 创建测试数据
std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 使用Iterator_range包装vector的范围
CGAL::Iterator_range range(vec.begin(), vec.end());
// 使用范围for循环遍历
std::cout << "Range contents: ";
for (int x : range) {
std::cout << x << " ";
}
std::cout << std::endl;
// 使用STL算法
auto it = std::find(range.begin(), range.end(), 5);
if (it != range.end()) {
std::cout << "Found: " << *it << std::endl;
}
// 检查范围属性
std::cout << "Size: " << range.size() << std::endl;
std::cout << "Empty: " << (range.empty() ? "yes" : "no") << std::endl;
// 转换为其他容器
auto list = range.to<std::list>();
std::cout << "Converted to list: ";
for (int x : list) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}4.2 示例2:Transform_iterator使用
#include <CGAL/Iterator_transform.h>
#include <CGAL/Iterator_range.h>
#include <vector>
#include <iostream>
#include <cmath>
// 定义变换函数对象
struct Square {
typedef double argument_type;
typedef double result_type;
result_type operator()(argument_type x) const {
return x * x;
}
};
struct DistanceFromOrigin {
typedef std::pair<double, double> argument_type;
typedef double result_type;
result_type operator()(const argument_type& p) const {
return std::sqrt(p.first * p.first + p.second * p.second);
}
};
int main() {
// 示例1:数值变换
std::vector<double> numbers = {1.0, 2.0, 3.0, 4.0, 5.0};
// 创建变换迭代器,计算平方
typedef CGAL::Iterator_transform<std::vector<double>::iterator, Square>
Square_iterator;
Square_iterator begin(numbers.begin());
Square_iterator end(numbers.end());
std::cout << "Squares: ";
for (auto it = begin; it != end; ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 示例2:坐标点距离变换
std::vector<std::pair<double, double>> points = {
{3.0, 4.0}, // 距离5
{0.0, 5.0}, // 距离5
{6.0, 8.0} // 距离10
};
typedef CGAL::Iterator_transform<
std::vector<std::pair<double, double>>::iterator,
DistanceFromOrigin> Distance_iterator;
Distance_iterator dbegin(points.begin());
Distance_iterator dend(points.end());
std::cout << "Distances from origin: ";
for (auto it = dbegin; it != dend; ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 使用Iterator_range包装变换迭代器
CGAL::Iterator_range<Distance_iterator> distance_range(dbegin, dend);
double sum = 0.0;
for (double d : distance_range) {
sum += d;
}
std::cout << "Sum of distances: " << sum << std::endl;
return 0;
}4.3 示例3:Filter_iterator使用
#include <CGAL/iterator.h>
#include <vector>
#include <iostream>
// 定义过滤谓词
struct IsEven {
typedef std::vector<int>::iterator argument_type;
bool operator()(argument_type it) const {
return (*it) % 2 == 0;
}
};
struct IsGreaterThan {
int threshold;
explicit IsGreaterThan(int t) : threshold(t) {}
typedef std::vector<int>::iterator argument_type;
bool operator()(argument_type it) const {
return (*it) <= threshold;
}
};
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 过滤出奇数(跳过偶数)
typedef CGAL::Filter_iterator<std::vector<int>::iterator, IsEven>
Odd_iterator;
IsEven is_even;
Odd_iterator begin(numbers.end(), is_even, numbers.begin());
Odd_iterator end(numbers.end(), is_even);
std::cout << "Odd numbers: ";
for (auto it = begin; it != end; ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 过滤出大于5的数
typedef CGAL::Filter_iterator<std::vector<int>::iterator, IsGreaterThan>
Greater_iterator;
IsGreaterThan gt5(5);
Greater_iterator gbegin(numbers.end(), gt5, numbers.begin());
Greater_iterator gend(numbers.end(), gt5);
std::cout << "Numbers greater than 5: ";
for (auto it = gbegin; it != gend; ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 使用lambda和std::function
auto is_prime = [](std::vector<int>::iterator it) -> bool {
int n = *it;
if (n < 2) return true; // 跳过0,1
for (int i = 2; i * i <= n; ++i) {
if (n % i == 0) return true; // 不是质数,跳过
}
return false; // 是质数,保留
};
typedef CGAL::Filter_iterator<std::vector<int>::iterator, decltype(is_prime)>
Prime_iterator;
Prime_iterator pbegin(numbers.end(), is_prime, numbers.begin());
Prime_iterator pend(numbers.end(), is_prime);
std::cout << "Prime numbers: ";
for (auto it = pbegin; it != pend; ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}4.4 示例4:组合使用多个适配器
#include <CGAL/Iterator_range.h>
#include <CGAL/Iterator_transform.h>
#include <CGAL/iterator.h>
#include <vector>
#include <iostream>
#include <numeric>
// 定义变换和过滤
struct Normalize {
typedef double argument_type;
typedef double result_type;
double sum;
explicit Normalize(double s) : sum(s) {}
result_type operator()(argument_type x) const {
return x / sum;
}
};
struct IsSmall {
typedef std::vector<double>::iterator argument_type;
double threshold;
explicit IsSmall(double t) : threshold(t) {}
bool operator()(argument_type it) const {
return *it < threshold;
}
};
int main() {
std::vector<double> data = {10.0, 20.0, 30.0, 40.0, 50.0};
// 计算总和
double sum = std::accumulate(data.begin(), data.end(), 0.0);
std::cout << "Sum: " << sum << std::endl;
// 创建归一化变换迭代器
typedef CGAL::Iterator_transform<std::vector<double>::iterator, Normalize>
Normalize_iterator;
Normalize norm(sum);
Normalize_iterator nbegin(data.begin(), norm);
Normalize_iterator nend(data.end(), norm);
// 包装为范围
CGAL::Iterator_range<Normalize_iterator> normalized_range(nbegin, nend);
std::cout << "Normalized values: ";
for (double v : normalized_range) {
std::cout << v << " ";
}
std::cout << std::endl;
// 进一步过滤小值(< 0.15)
// 注意:这里需要基于原始vector创建过滤迭代器
// 因为过滤谓词作用于迭代器而非值
IsSmall is_small(15.0); // 过滤原始值小于15的
typedef CGAL::Filter_iterator<std::vector<double>::iterator, IsSmall>
Filtered_iterator;
Filtered_iterator fbegin(data.end(), is_small, data.begin());
Filtered_iterator fend(data.end(), is_small);
std::cout << "Values >= 15: ";
for (auto it = fbegin; it != fend; ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 组合:先过滤再变换
// 创建过滤后数据的归一化视图
std::vector<double> filtered_data;
for (auto it = fbegin; it != fend; ++it) {
filtered_data.push_back(*it);
}
double filtered_sum = std::accumulate(filtered_data.begin(),
filtered_data.end(), 0.0);
Normalize norm_filtered(filtered_sum);
Normalize_iterator nfbegin(filtered_data.begin(), norm_filtered);
Normalize_iterator nfend(filtered_data.end(), norm_filtered);
std::cout << "Normalized filtered values: ";
for (auto it = nfbegin; it != nfend; ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}5. 复杂度分析
5.1 时间复杂度
| 操作 | Iterator_range | Transform_iterator | Filter_iterator | Counting_iterator |
|---|---|---|---|---|
| 构造 | O(1) | O(1) | O(1) | O(1) |
| begin/end | O(1) | O(1) | O(1) | O(1) |
| 解引用(*) | O(1) | O(f) | O(1) | O(1) |
| 前向递增(++) | O(1) | O(1) | O(k) | O(1) |
| 双向递减(—) | O(1) | O(1) | O(k) | N/A |
| 随机访问[n] | O(1) | O(1) | O(kn) | N/A |
| size() | O(n) | N/A | N/A | N/A |
其中:
- f = 变换函数的时间复杂度
- k = 平均需要跳过的元素数
- n = 范围大小
5.2 空间复杂度
| 适配器 | 额外空间 | 说明 |
|---|---|---|
| Iterator_range | 2 × sizeof(I) | 存储begin和end |
| Transform_iterator | sizeof(I) + sizeof(Fct) | 存储迭代器和函数对象 |
| Filter_iterator | 2 × sizeof(I) + sizeof(P) | 存储当前、结束位置和谓词 |
| Counting_iterator | sizeof(I) + sizeof(size_t) | 存储迭代器和计数器 |
5.3 与标准容器的对比
| 特性 | std::vector | std::list | Iterator_range |
|---|---|---|---|
| 内存连续性 | 是 | 否 | 取决于底层 |
| 动态扩容 | 是 | 是 | 否 |
| 所有权 | 有 | 有 | 无 |
| 生命周期管理 | 自动 | 自动 | 引用 |
| 适用场景 | 数据存储 | 频繁插入删除 | 算法接口 |
6. 关键文件位置
| 文件路径 | 说明 |
|---|---|
STL_Extension/include/CGAL/Iterator_range.h | Iterator_range类定义 |
STL_Extension/include/CGAL/Iterator_transform.h | Transform_iterator定义 |
STL_Extension/include/CGAL/iterator.h | Filter_iterator、Counting_iterator等 |
STL_Extension/include/CGAL/Counting_iterator.h | 计数迭代器(已合并到iterator.h) |
STL_Extension/include/CGAL/N_step_adaptor.h | N步适配器 |
STL_Extension/include/CGAL/Prevent_deref.h | 阻止解引用适配器 |
7. 最佳实践
7.1 使用建议
-
优先使用make_range工厂函数:
auto range = CGAL::make_range(container.begin(), container.end()); -
避免在Filter_iterator上使用随机访问操作: 过滤迭代器的随机访问需要线性扫描,效率低下。
-
注意Transform_iterator返回rvalue: 如果需要修改原始数据,应使用普通迭代器而非变换迭代器。
-
C++20中使用结构化绑定:
auto [begin, end] = CGAL::make_range(container.begin(), container.end());
7.2 常见陷阱
-
生命周期问题:
Iterator_range不拥有底层数据,确保范围在使用期间底层容器有效。 -
过滤迭代器的终止条件:
// 错误:可能跳过终止位置 while (it != end && predicate(it)) ++it; // 正确:Filter_iterator自动处理 for (; it != end; ++it) { ... } -
变换函数的副作用: 变换函数应该是纯函数,避免副作用导致不可预期的行为。