Boost C++ 库

...世界上最受推崇和专业设计的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, C++ 编码标准

Next

第 1 章。 Boost.Icl

Joachim Faulhaber

根据 Boost 软件许可 1.0 版分发。(请参阅随附文件 LICENSE_1_0.txt 或在 https://boost.ac.cn/LICENSE_1_0.txt 复制)

目录

简介
定义和基本示例
Icl 的类模板
区间合并样式
示例
概述
聚会
区间
动态区间
静态区间
区间容器
重叠计数器
聚会客人的平均身高
聚会中最高的客人
月份和周的时间网格
人力
用户组
Std 复制
Std 转换
自定义区间
项目
大型位集
概念
命名
方面
集合和映射
可加性、可减性和重叠聚合
映射特征
语义
排序和等价
集合
映射
收集器:集合的映射
量词:数字的映射
概念归纳
接口
类模板
所需概念
关联类型
函数概要
自定义
区间
实现
迭代大小
复杂度
原地和中缀运算符
函数参考
重载表
分段精细度
键类型
构造、复制、析构
包含性
等价和排序
大小
范围
选择
加法
减法
插入
擦除
交集
对称差
迭代器相关
元素迭代
流式传输、转换
区间构造
其他区间排序
其他区间函数
致谢
区间容器库参考
头文件 <boost/icl/closed_interval.hpp>
头文件 <boost/icl/continuous_interval.hpp>
头文件 <boost/icl/discrete_interval.hpp>
头文件 <boost/icl/dynamic_interval_traits.hpp>
头文件 <boost/icl/functors.hpp>
头文件 <boost/icl/gregorian.hpp>
头文件 <boost/icl/impl_config.hpp>
头文件 <boost/icl/interval.hpp>
头文件 <boost/icl/interval_base_map.hpp>
头文件 <boost/icl/interval_base_set.hpp>
头文件 <boost/icl/interval_bounds.hpp>
头文件 <boost/icl/interval_combining_style.hpp>
头文件 <boost/icl/interval_map.hpp>
头文件 <boost/icl/interval_set.hpp>
头文件 <boost/icl/interval_traits.hpp>
头文件 <boost/icl/iterator.hpp>
头文件 <boost/icl/left_open_interval.hpp>
头文件 <boost/icl/map.hpp>
头文件 <boost/icl/open_interval.hpp>
头文件 <boost/icl/ptime.hpp>
头文件 <boost/icl/rational.hpp>
头文件 <boost/icl/right_open_interval.hpp>
头文件 <boost/icl/separate_interval_set.hpp>
头文件 <boost/icl/split_interval_map.hpp>
头文件 <boost/icl/split_interval_set.hpp>
[Note] 注意

C++03 支持Boost.Icl 1.84 中已被弃用,并将在 Boost.Icl 1.86 中移除。

区间在软件开发中几乎无处不在。然而,它们很容易通过一对数字编码到用户定义的类中,因此大多数时候只是隐式地使用。区间的含义很简单。它们表示其下限和上限之间的所有元素,因此是一个集合。但与集合不同,区间通常不能添加到单个新区间。如果您想将区间添加到一个仍然表示集合的区间集合中,您就会想到这个库提供的interval_sets 的概念。

ICL 的区间容器最初是在 Cortex Software GmbH 开发的,目的是解决医院信息系统中与日期和时间区间计算相关的问题。具有关联值(如发票金额治疗方案集合)的时间区间必须在统计、计费程序和治疗计划程序中进行操作。因此,ICL 从这些工业用例中应运而生。它提取了通用代码,有助于解决日期和时间问题领域中的常见问题,并且在其他领域也可能受益。

区间容器最有利的方面之一是它们对集合和映射的非常紧凑的表示。如果在一个给定的问题域中,元素通常以连续块的形式出现,那么使用元素的集合和映射可能非常低效。除了可以大幅降低空间和时间成本的关联容器的紧凑表示之外,ICL 还配备了一种通用的聚合机制,允许在区间重叠时以有意义的方式组合关联值。

对于简要的介绍和概述,您可以查看 关于 ICL 的演示材料,来自 BoostCon2009

区间容器库 (ICL) 提供了 intervals 和两种区间容器:interval_setsinterval_maps

  • interval_set 是一个集合,它被实现为一组区间。
  • interval_map 是一个映射,它被实现为区间值对的映射。
两个方面

Interval_setsinterval_maps 在其接口中暴露了两个不同的方面:(1)集合或映射的功能,这是更抽象的方面。以及(2)区间容器的功能,这是更具体和实现相关的方面。在实践中,这两个方面都很有用,因此都得到了支持。

第一个方面,将称为基本 方面,是更重要的一个。这意味着我们可以像使用元素的集合或映射一样使用 interval_setinterval_map。它暴露了相同的函数。

interval_set<int> mySet;
mySet.insert(42);
bool has_answer = contains(mySet, 42);

第二个方面,将称为分段 方面,允许利用以下事实:interval_setsinterval_maps 的元素聚集在我们可以迭代的区间中。

// Switch on my favorite telecasts using an interval_set
interval<seconds>::type news(make_seconds("20:00:00"), make_seconds("20:15:00"));
interval<seconds>::type talk_show(make_seconds("22:45:30"), make_seconds("23:30:50"));
interval_set<seconds> myTvProgram;
myTvProgram.add(news).add(talk_show);

// Iterating over elements (seconds) would be silly ...
for(interval_set<seconds>::iterator telecast = myTvProgram.begin();
    telecast != myTvProgram.end(); ++telecast)
    //...so this iterates over intervals
   TV.switch_on(*telecast);

每当集合的元素以连续块出现时,使用 interval_setsinterval_maps 可能会有所帮助:intervals。在许多问题领域,尤其是在处理与日期和时间相关的计算的领域中,情况显然如此。

可加性和可减性

std::setsmaps 不同,interval_setsinterval_maps 实现了 AddableSubtractable 概念。因此,interval_sets 定义了一个 operator +=,它自然地实现为集合并集,以及一个 operator -=,它因此实现为集合差集。在 Icl 中,interval_maps 也是可加和可减的。事实证明,将加法或减法传播到 interval_map 的关联值是一个非常有用的概念,在将区间值对插入到 interval_map 中导致插入的区间值对与已经在 interval_map 中的区间值对发生冲突的情况下。这种操作传播称为重叠聚合

重叠聚合

这是一个非常小的聚会的第一个激励性示例,演示了 interval_maps 上的 重叠聚合 原则

在示例中,玛丽首先进入聚会。她在 [20:00,22:00) 时间区间内参加。哈利稍后进入。他停留的时间在 [21:00,23:00) 内。

typedef std::set<string> guests;
interval_map<time, guests> party;
party += make_pair(interval<time>::right_open(time("20:00"), time("22:00")), guests("Mary"));
party += make_pair(interval<time>::right_open(time("21:00"), time("23:00")), guests("Harry"));
// party now contains
[20:00, 21:00)->{"Mary"}
[21:00, 22:00)->{"Harry","Mary"} //guest sets aggregated on overlap
[22:00, 23:00)->{"Harry"}

在区间重叠时,相应的名称集合被累积。在重叠点,区间被分割。区间重叠时内容的累积是通过一个 operator += 完成的,该运算符必须为 interval_map 的关联值实现。在示例中,关联值是 guest sets。因此,一个 guest set 必须将 operator += 实现为集合并集。

从示例中可以看出,interval_map 既具有分解行为(在时间维度上),又具有累积行为(在关联值上)。

可加性和重叠聚合是 interval_maps 上的有用功能,通过函数 addoperator += 实现。但是您也可以将它们与传统的 插入语义 一起使用,其行为类似于为区间插入泛化的 std::map::insert

除了区间容器之外,我们还可以使用与区间容器行为相等的元素容器:在基本方面,它们具有完全相同的功能。STL 的 std::set 就是这样一个等效的集合实现。由于 icl 的区间映射的聚合功能,std::map 在根本上与 interval_map 不完全等效。因此,在 icl 中有一个额外的 icl::map 类模板用于元素映射。

下表概述了 icl 提供的主要类模板。

表 1.1. 区间类模板

形式

模板

静态边界

非对称

right_open_interval

left_open_interval

对称

closed_interval

open_interval

动态边界

discrete_interval

continuous_interval


静态边界区间始终具有相同类型的区间边界,例如,[a..b) 的右开边界,用于 right_open_interval。动态边界区间可以具有不同的边界。有关详细信息,请参阅关于 区间 的章节。

表 1.2. 容器类模板

粒度

样式

集合

映射

区间

连接

interval_set

interval_map

分离

separate_interval_set

分割

split_interval_set

split_interval_map

元素

(std::set )

map


Std::set 放在括号中,因为它不是 ICL 的类模板。但是,它可以作为元素容器使用,在基本方面,它与 ICL 的区间集合行为相等。列 样式 指的是区间容器组合添加区间的不同方式。这些组合样式在下一节中描述。

当我们向区间容器添加区间或区间值对时,可以以不同的方式添加区间:区间可以连接或分割或保持分离。下表中的示例显示了不同的区间合并样式。

表 1.3. 区间容器组合区间的方式

连接

分离

分割

集合

interval_set

separate_interval_set

split_interval_set

map

interval_map

split_interval_map

区间在重叠或接触时连接
(如果关联值相等)。

区间在重叠时连接,不在接触时连接。

区间在重叠时分割。
所有区间边界都保留。


表 1.4. 区间组合样式示例

连接

分离

分割

集合

interval_set A

separate_interval_set B

split_interval_set C

  {[1      3)          }
+       [2      4)
+                 [4 5)
= {[1                5)}

  {[1      3)}         }
+       [2      4)
+                 [4 5)
= {[1           4)[4 5)}

  {[1      3)          }
+       [2      4)
+                 [4 5)
= {[1 2)[2 3)[3 4)[4 5)}

map

interval_map D

split_interval_map E

  {[1      3)->1          }
+       [2      4)->1
+                 [4 5)->1
= {[1 2)[2 3)[3      5)   }
  | ->1  ->2     ->1      |

  {[1      3)->1          }
+       [2      4)->1
+                 [4 5)->1
= {[1 2)[2 3)[3 4)[4 5)   }
  | ->1  ->2  ->1  ->1    |


请注意,interval_sets ABC 表示相同的元素集合 {1,2,3,4},而 interval_maps DE 表示相同的元素映射 {1->1, 2->2, 3->1, 4->1}。有关其他演示,请参阅示例程序 区间容器

连接区间容器

Interval_setinterval_map 始终处于最小表示形式。这在许多情况下很有用,在这些情况下,区间的插入点或交点并不重要。因此,在大多数情况下,interval_setinterval_map 将是区间容器的首选。

分割区间容器

Split_interval_setsplit_interval_map 相反,具有插入内存。它们会累积来自添加和交集的区间边界。如果我们想用某些时间网格(例如月份或日历周或两者)来丰富区间容器,这将特别有用。请参阅示例 月份和周的时间网格

分离区间容器

Separate_interval_set 实现了分离样式。这种样式保留了永远不会被重叠区间穿过的边界。因此,如果插入到 separate_interval_set 中的所有区间都是从某个永不通过月份边界的网格生成的,那么这些边界将保留在 separate_interval_set 中。

14:46 15.10.2010


Next