- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
语境
我正在尝试实现类似容器的nD数组。可以包装基础序列容器并允许将其作为(of ...)容器的容器进行处理的东西:arr[i][j][k]
应该是_arr[(((i * dim2) + j) * dim3) + k]
的(最终是const)引用。
好的,直到那里,arr[i]
只是要成为子数组的包装类。
当我尝试实现干预者时,我突然意识到周围到处都是龙:
operator []
返回代理或包装而不是真实引用(When Is a Container Not a Container?)Forward iterators [forward.iterators]
...
6 Ifa
andb
are both dereferenceable, thena == b
if and only if*a
and*b
are bound to the same object.
vector<bool>
不遵守容器的所有要求,因为它返回代理而不是引用:Class vector [vector.bool]
...
3 There is no requirement that the data be stored as a contiguous allocation of bool values. A space-optimized representation of bits is recommended instead.
4 reference is a class that simulates the behavior of references of a single bit in vector.
path iterators [fs.path.itr]
...
2 A path::iterator is a constant iterator satisfying all the requirements of a bidirectional iterator (27.2.6) except that, for dereferenceable iteratorsa
andb
of type path::iterator witha == b
, there is no requirement that*a
and*b
are bound to the same object.
Notes: std::reverse_iterator does not work with iterators that return a reference to a member object (so-called "stashing iterators"). An example of stashing iterator is std::filesystem::path::iterator.
std::reverse_iterator
时,它立即中断了)
最佳答案
好的,我们有两个相似但截然不同的概念。因此,让他们进行布局。
但是首先,我需要区分C++-pre-20的命名要求和为Ranges TS创建并包含在C++ 20中的实际语言内概念。它们都被称为“概念”,但是它们的定义有所不同。因此,当我谈论小写字母c的概念时,我的意思是C++ 20之前的要求。当我谈论“带有空间C的概念”时,我指的是C++ 20的东西。
代理迭代器
代理迭代器是迭代器,其中reference
不是value_type&
,而是其他一些类型,其行为类似于对value_type
的引用。在这种情况下,*it
将prvalue返回到此reference
。
InputIterator概念除了可以转换为reference
之外,没有对value_type
施加任何要求。但是,ForwardIterator概念明确声明“reference
是对T
的引用”。
因此,代理迭代器不能满足ForwardIterator概念。但是它仍然可以是InputIterator。因此,您可以安全地将代理迭代器传递给仅需要InputIterators的任何函数。
因此,vector<bool>
迭代器的问题不在于它们是代理迭代器。当他们实际上只是InputIterators和OutputIterators时,他们 promise 将满足RandomAccessIterator概念(尽管使用了适当的标记)。
C++ 20中采用的Ranges提议(大多数情况下)对迭代器概念进行了更改,使代理迭代器适用于所有迭代器。因此,在Ranges下,vector<bool>::iterator
确实实现了RandomAccessIterator概念。因此,如果您针对Ranges概念编写了代码,则可以使用各种代理迭代器。
这对于处理诸如计数范围之类的事情非常有用。您可以将reference
和value_type
设为相同的类型,因此您只能以任何一种方式处理整数。
当然,如果您可以控制使用迭代器的代码,则只要不违反编写迭代器所依据的概念,就可以使其执行所需的任何操作。
隐藏式迭代器
隐藏式迭代器是迭代器,其中reference_type
是(直接或间接)对存储在迭代器中的对象的引用。因此,如果您复制迭代器,则该副本将返回对与原始对象不同的对象的引用,即使它们引用的是同一元素。并且当您增加迭代器时,先前的引用将不再有效。
通常实现隐藏式迭代器,因为计算要返回的值非常昂贵。可能涉及内存分配(例如path::iterator
),或者涉及可能仅执行一次的复杂操作(例如regex_iterator
)。因此,您只想在必要时这样做。
ForwardIterator作为概念(或概念)的基础之一是,这些迭代器的范围代表独立于其迭代器而存在的值的范围。这样可以进行多遍操作,但也可以使其他事情变得有用。您可以存储对范围内项目的引用,然后在其他地方进行迭代。
如果需要迭代器成为ForwardIterator或更高版本,则永远不要使其成为隐藏式迭代器。当然,C++标准库并不总是与其自身保持一致。但是它通常会指出其不一致之处。path::iterator
是一个隐藏的迭代器。该标准说它是一个BidirectionalIterator。但是,它也为该类型提供了引用/指针保留规则的异常(exception)。这意味着您不能将path::iterator
传递给任何可能依赖该保留规则的代码。
现在,这并不意味着您不能将其传递给任何东西。任何仅需要InputIterator的算法都将能够采用这样的迭代器,因为此类代码无法依赖该规则。当然,可以使用您编写的任何代码或在其文档中明确声明不依赖该规则的任何代码。但是,即使它说它是BidirectionalIterator,也不能保证可以在上面使用reverse_iterator
。
在这方面,regex_iterator
甚至更糟。据说它们是基于其标签的ForwardIterators,但是标准从未说过它们实际上是ForwardIterators(与path::iterator
不同)。而且,由于将reference
作为对成员对象的实际引用而指定了它们,这使它们不可能成为真正的ForwardIterators。
请注意,在C++ 20之前的概念和Ranges概念之间没有区别。这是因为ForwardIterator概念仍然禁止存储迭代器。 This is by design.
用法
现在显然,您可以在代码中做任何您想做的事情。但是您无法控制的代码将归其所有者所有。他们将针对旧概念,新概念或它们指定的其他某些c / Concept或要求进行写作。因此,您的迭代器需要能够与他们的需求兼容。
Ranges附加功能带来的算法使用了新的Concepts,因此您始终可以依靠它们与代理迭代器一起使用。但是,据我所知,范围概念并未移植到较旧的算法中。
就个人而言,我建议避免完全隐藏迭代器实现。通过提供对代理迭代器的完全支持,可以将大多数隐藏式迭代器重写为返回值,而不是对对象的引用。
例如,如果存在path_view
类型,则path::iterator
可能会返回该类型,而不是完整的path
。这样,如果您要执行昂贵的复制操作,则可以。同样,regex_iterator
可以返回match对象的副本。新概念通过支持代理迭代器使以这种方式工作成为可能。
现在,隐藏式迭代器以一种有用的方式处理缓存。迭代器可以缓存其结果,以便重复使用*it
仅执行一次昂贵的操作。但是请记住隐藏迭代器的问题:返回对其内容的引用。您不需要这样做只是为了获得缓存。您可以将结果缓存在optional<T>
中(当迭代器增加/减少时,该代码将无效)。因此,您仍然可以返回一个值。它可能涉及其他副本,但reference
不应为复杂类型。
当然,所有这些都意味着auto &val = *it;
不再是合法代码。但是,auto &&val = *it;
将始终有效。实际上,这是Range TS版本迭代器的很大一部分。
关于c++ - 代理容器上的迭代器可能是 “least bad implementation”?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51046897/
我们的电脑在使用的过程中,有的小伙伴在上网的时候可能就遇到过系统提示:400 bad request的情况。据小编所知这种情况,大致意思就是出现了错误的请求或者请求不能满足。原因是因为我们请求的语法
您可以尝试清除浏览器缓存 访问一下你的FTP看是否可以登陆 成功解决502 Bad Gateway错误 今天登陆博客,显示502 bad gateway,NGINX最烦人的地方就是经常会出现这个
我想要具有 FIFO 的服务器-客户端模型和客户端获取目录路径,但我收到错误“读:错误地址”和“写:错误地址”。 客户端 服务器错误:“读取:地址错误” 客户端错误:“写入:地址错误” 最佳答案 您可
Agda 手册 Inductive Data Types and Pattern Matching状态: To ensure normalisation, inductive occurrences
我正在使用 maven-compiler-plugin:2.3.2 并且每次我对在导入中具有枚举 (ContentType) 的类进行更改时,我需要使 干净,否则它会给我: ERROR] Failed
我想发布我的第一个 Facebook 应用程序,需要一个隐私政策 URL。 我在我的网站上发布了 privacypolicy.html 页面,但是当我在“应用程序详细信息”中配置它时,我收到了下一条消
vscode 1.45.1版本使用克隆存储库时,我收到“Bad credentials”。最近我在github上换了用户名。可能就是这个原因。我如何告诉vs code?
我正在 Mac OS 终端上创建 cron,代码如下: home.cron 的内容: * * * * * /users/username/desktop/forTrump/script.sh 然后我这
我是新手,所以需要任何帮助,当我要求一个例子时,我的教授给我了这段代码,我希望有一个工作模型...... from numpy import loadtxt import numpy as np fr
我使用 linux 服务器已经有一段时间了,通过使用 cifs 挂载到多个 Windows 共享。 到目前为止,我总是在/etc/fstab 中有一行://IPADDRESS/sharename/mn
请大家帮帮我我正在尝试使用 NUTCH 抓取网站,但它给我错误“java.io.IOException: Job failed!” 我正在运行此命令“bin/nutch solrindex http:
我想创建我的基础业务类,例如 EntityBase,以具有一些常见的行为,例如实现用于跟踪对象更改的接口(interface)(IsNew、IsDirty)和 INotifyPropertyChang
我们最近开发了一个基于 SOA 的站点,但是这个站点在负载过重时最终会出现严重的负载和性能问题。我在这里发布了一个与此问题相关的问题: ASP.NET website becomes unrespon
我们的 Azure 功能已开始返回 502 Bad Gateways,但并非所有调用都返回。我没有使用“间歇性”这个词,因为它总是进行相同类型的调用,但现在总是使用相同的数据。 常规配置 Azure
我假设在字典中进行查找时,它需要散列您提供的 key ,然后使用该散列来查找您要查找的对象。 如果是这样,使用较大的对象作为键是否会显着减慢查找速度或产生其他使用字符串或简单数据类型作为键不会遇到的后
我的代码如下: public static final Condition.ActionCondition ACTION_CONDITION_ACTIVATE = new Condit
大家好,我有一个应用程序和一个表单,我要求用户在其中输入地址,并在文本字段下方显示带有标记的谷歌地图,用户可以在其中将标记拖/放到正确的位置。问题是,在显示 map 的开始时,它只是部分显示而不是全部
给定字节矩阵(所有值在内存中都是 1 位),如果其中至少有一个零,则称其为原始列或“坏”列。查找算法,占用 O(1) 额外内存。 如果没有另一个值(如 -1)或另一个重复矩阵来跟踪已经找到的空值,并且
当我创建一个标准类时,我主要这样做: $test = null; $test->id = 1; $test->name = 'name'; 但是在严格模式下我得到一个错误。 显然正确的做法是: $te
我试图理解为什么将 -O2 -march=native 与 GCC 一起使用会比不使用它们时产生更慢的代码。请注意,我在 Windows 7 下使用 MinGW (GCC 4.7.1)。 这是我的代码
我是一名优秀的程序员,十分优秀!