相关章节: 循环迭代器 | 属性映射 | 半边数据结构 | 组合地图

3.1 CGAL的STL扩展

1. 理论基础

1.1 范围概念(Range)的数学理论

在计算几何算法中,**范围(Range)**是一个核心抽象概念。从数学角度看,范围可以定义为一个有序对 ,其中 是起始迭代器, 是终止迭代器,表示半开区间

CGAL的范围概念扩展了STL的迭代器范围,提供了以下数学性质:

定义 1.1(范围):设 为迭代器类型,范围 是满足以下条件的有序对:

  • ,返回起始迭代器
  • ,返回终止迭代器
  • 可通过解引用访问

定义 1.2(范围类别)

  1. Forward_range: 支持前向遍历,满足 操作
  2. Bidirectional_range: 支持双向遍历,满足 操作
  3. Random_access_range: 支持随机访问,满足 操作

1.2 与C++20 Ranges的对比

特性CGAL Iterator_rangeC++20 std::ranges
标准符合性C++11/14/17兼容需要C++20
概念定义基于Boost.Range原生语言支持
惰性求值不支持支持views
管道操作不支持支持 |> 操作符
Borrowed rangeC++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)**的典型应用,它允许在不修改原始迭代器的情况下,改变其行为或接口。

设计原则

  1. 单一职责原则:每个适配器只负责一种转换
  2. 开闭原则:对扩展开放,对修改封闭
  3. 最小惊讶原则:适配器的行为应符合用户预期

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;
#endif

3.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 CGAL

3.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_rangeTransform_iteratorFilter_iteratorCounting_iterator
构造O(1)O(1)O(1)O(1)
begin/endO(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/AN/AN/A

其中:

  • f = 变换函数的时间复杂度
  • k = 平均需要跳过的元素数
  • n = 范围大小

5.2 空间复杂度

适配器额外空间说明
Iterator_range2 × sizeof(I)存储begin和end
Transform_iteratorsizeof(I) + sizeof(Fct)存储迭代器和函数对象
Filter_iterator2 × sizeof(I) + sizeof(P)存储当前、结束位置和谓词
Counting_iteratorsizeof(I) + sizeof(size_t)存储迭代器和计数器

5.3 与标准容器的对比

特性std::vectorstd::listIterator_range
内存连续性取决于底层
动态扩容
所有权
生命周期管理自动自动引用
适用场景数据存储频繁插入删除算法接口

6. 关键文件位置

文件路径说明
STL_Extension/include/CGAL/Iterator_range.hIterator_range类定义
STL_Extension/include/CGAL/Iterator_transform.hTransform_iterator定义
STL_Extension/include/CGAL/iterator.hFilter_iterator、Counting_iterator等
STL_Extension/include/CGAL/Counting_iterator.h计数迭代器(已合并到iterator.h)
STL_Extension/include/CGAL/N_step_adaptor.hN步适配器
STL_Extension/include/CGAL/Prevent_deref.h阻止解引用适配器

7. 最佳实践

7.1 使用建议

  1. 优先使用make_range工厂函数

    auto range = CGAL::make_range(container.begin(), container.end());
  2. 避免在Filter_iterator上使用随机访问操作: 过滤迭代器的随机访问需要线性扫描,效率低下。

  3. 注意Transform_iterator返回rvalue: 如果需要修改原始数据,应使用普通迭代器而非变换迭代器。

  4. C++20中使用结构化绑定

    auto [begin, end] = CGAL::make_range(container.begin(), container.end());

7.2 常见陷阱

  1. 生命周期问题Iterator_range不拥有底层数据,确保范围在使用期间底层容器有效。

  2. 过滤迭代器的终止条件

    // 错误:可能跳过终止位置
    while (it != end && predicate(it)) ++it;
     
    // 正确:Filter_iterator自动处理
    for (; it != end; ++it) { ... }
  3. 变换函数的副作用: 变换函数应该是纯函数,避免副作用导致不可预期的行为。