网站首页 > 博客文章 正文
使迭代器与 STL 迭代器特性兼容
许多 STL 算法要求迭代器符合某些特性。不幸的是,这些要求在编译器、系统和 C++ 版本之间不一致。
对于我们的目的,我们将使用创建可迭代范围食谱中的类来说明这个问题。如果你在继续之前阅读了那个食谱,可能会更容易理解。
在 main() 中,如果我添加一个调用 minmax_element() 算法:
Seq<int> r{100, 110};
auto [min_it, max_it] = minmax_element(r.begin(), r.end());
cout << format("{} - {}\n", *min_it, *max_it);
它不编译。错误消息是模糊的、神秘的,并且是级联的,但如果你仔细观察,你会发现我们的迭代器不符合与此算法兼容的要求。
好的,我们来修复它。
如何做到这一点…
我们需要对我们的迭代器做一些简单的添加,使其与算法兼容。我们的迭代器需要满足前向迭代器的最低要求,所以让我们从这里开始:
我们几乎拥有前向迭代器所需的所有运算符。我们缺少的唯一一个是等同比较运算符 ==。我们可以很容易地通过 operator==() 重载将这个添加到我们的迭代器中:
bool operator==(const iterator& other) const {
return value_ == other.value_;
}
有趣的是,这使得代码在某些系统上编译和运行,但在 Clang 上不行,我们得到错误消息:
No type named 'value_type' in 'std::iterator_traits<Seq<int>::iterator>'
这告诉我,我们需要在迭代器中设置特性。
迭代器特性类在迭代器类中查找一组类型定义(实现为 using 别名):
public:
using iterator_concept = std::forward_iterator_tag;
using iterator_category = std::forward_iterator_tag;
using value_type = std::remove_cv_t<T>;
using difference_type = std::ptrdiff_t;
using pointer = const T*;
using reference = const T&;
我倾向于将这些放在迭代器类 public: 部分的顶部,这样它们很容易看到。
现在我们有一个完全符合要求的前向迭代器类,代码在我所有的编译器上运行。
它是如何工作的…
using 语句是可能用于定义迭代器可以执行的功能的特性。让我们来看看它们中的每一个:
using iterator_concept = std::forward_iterator_tag;
using iterator_category = std::forward_iterator_tag;
前两个是类别和概念,都设置为 forward_iterator_tag。这个值表示迭代器符合前向迭代器规范。
一些代码不看这些值,而是寻找单独的设置和功能:
using value_type = std::remove_cv_t<T>;
using difference_type = std::ptrdiff_t;
using pointer = const T*;
using reference = const T&;
value_type 别名设置为 std::remove_cv_t<T>,这是值的类型,去除了任何 const 限定符。
difference_type 别名设置为 std::ptrdiff_t,作为指针差异的特殊类型。
pointer 和 reference 别名分别设置为指针和引用的 const 限定版本。
为大多数迭代器定义这些类型别名是基本要求。
还有更多…
值得注意的是,定义这些特性允许我们使用概念限制模板与我们的迭代器。例如:
template<typename T>
requires std::forward_iterator<typename T::iterator>
void printc(const T & c) {
for(auto v : c) {
cout << format("{} ", v);
}
cout << '\n';
}
这个打印我们序列的函数受到 forward_iterator concept 的限制。如果我们的类没有资格,它就不会编译。
我们也可以使用 ranges:: 版本的算法:
auto [min_it, max_it] = ranges::minmax_element(r);
这使得使用我们的迭代器更方便。
我们可以使用静态断言测试 forward_range 兼容性:
static_assert(ranges::forward_range<Seq<int>>);
猜你喜欢
- 2024-10-12 C++核心准则T.24:用标签类或特征区分只有语义不同的概念
- 2024-10-12 用苹果发布会方式打开C++20(苹果在哪开发布会)
- 2024-10-12 C++核心准则T.25:避免互补性约束(规矩是一种约束,一种准则)
- 2024-10-12 C++核心准则T.21:为概念定义一套完整的操作
- 2024-10-12 C++核心准则T.5:结合使用泛型和面向对象技术应该增强效果
- 2024-10-12 C++经典书籍(c++相关书籍)
- 2024-10-12 C++一行代码实现任意系统函数Hook
- 2024-10-12 C++核心准则T.11:只要可能就使用标准概念
- 2024-10-12 C++核心准则T.48:如果不能用概念,用enable_if
- 2024-10-12 C++核心准则T.13:简单、单类型参数概念使用缩略记法更好
你 发表评论:
欢迎- 最近发表
-
- 给3D Slicer添加Python第三方插件库
- Python自动化——pytest常用插件详解
- Pycharm下安装MicroPython Tools插件(ESP32开发板)
- IntelliJ IDEA 2025.1.3 发布(idea 2020)
- IDEA+Continue插件+DeepSeek:开发者效率飙升的「三体组合」!
- Cursor:提升Python开发效率的必备IDE及插件安装指南
- 日本旅行时想借厕所、买香烟怎么办?便利商店里能解决大问题!
- 11天!日本史上最长黄金周来了!旅游万金句总结!
- 北川景子&DAIGO缘定1.11 召开记者会宣布结婚
- PIKO‘PPAP’ 洗脑歌登上美国告示牌
- 标签列表
-
- ifneq (61)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)