繁体   English   中英

容器的迭代器能否产生左值以外的东西?

[英]Can a container's iterator yield something other than an lvalue?

我或多或少得出的结论是,不可能编写一个其value_type没有直接存储在容器中的合格容器。 我认为这很不幸,因为我经常希望我有一些容器,其中值的类型要么是部分计算的,要么是由不连续的部分组成的(以下示例,但与问题不直接相关)。 我知道如何编写使用代理对象的迭代器,尽管这很烦人。 但是我现在想知道C ++标准中是否确实有此类野兽的空间。 这里的杂语太多了; tl; dr版本很简单:§24.2.5的第1段和第6段真正意味着什么,违反明显含义的程度将破坏标准算法? 或者,换句话说,如何解释它们以允许代理迭代器?

正如Pete Becker指出的那样,实际上没有什么可迫使我的容器符合对标准库容器提出的要求。 但是,为了使用具有许多标准算法的容器,它必须具有至少带有forward_iterator_tag的一致迭代器,或者必须基于该迭代器,但仍要设法满足特定算法对其施加的操作(如果不是形式上的)要求迭代器。

这是我的理由:

表96(第23.2.1节),容器要求,包括:

Expression     Return type         Assertion/note
------------   -------------       ---------------------
X::iterator    iterator type       any iterator category
               whose value         that meets the
               type is T           forward iterator
                                   requirements.
                                   Convertible to
                                   const_iterator.

 a.begin()     iterator;
               const_iterator for
               constant a.

现在,转发迭代器:

第24.2.5节,第 1:

如果……,则类或指针类型X满足正向迭代器的要求。

—如果X是一个可变迭代器,则reference是对T的引用; 如果X是const迭代器,则reference是对const T的引用

确实没有直接要求*a返回reference (其中aX类型)的要求。 要求是:

表107中的表(输入迭代器) *a如果a是不可引用的,则a必须“可转换为T”。

来自表106(迭代器)中的*r必须具有类型reference ,其中rX&类型X&并且是可取消引用的。

但是,表106还指定++r返回X& ,因此*++r必须是reference 此外,(按照表107), *a++必须是reference ,尽管(表109) a[n]仅需要“可转换为参考”。 我得说,我看不出*a ,其中a是类型的X*r其中, r是类型的X&可能是不同的,但也许我错过了一些微妙。

也许这里有个小摆动间,但不多。 在某个时候,如果容器中实际上没有T ,则需要准备创建T ,以便您可以提供对其的引用。

但关键是

第24.2.5节,第 6( ab是类型X值):如果ab都是可引用的,则当且仅当*a*b绑定到同一对象时, a == b

我找不到bound to的正式定义,但在我看来,制作不可寻址对象的迭代器的通常策略是创建一个代理对象,通常将其存储在迭代器本身内。 在这种情况下,除了禁止两个不同迭代器对象之间的相等比较成功外,即使它们在逻辑上指示相同的位置,也需要对“绑定到”以任何方式解释24.2.5 / 6的含义有非常宽泛的理解。在容器中。

另一方面,我注意到应该知道的DietmarKühl在回答这个问题时说:

C ++ 2011放宽了要求,并不一定需要使用迭代器才能产生左值

那么,迭代器可以返回代理吗? 如果可以的话,这种代理的性质是什么? 我的推理这样的迭代器不合格的原因在哪里失败?


如所承诺的,一些有效value_types不会连续存储在容器中的容器:

1)一个紧凑的关联容器,其键和值类型可以更有效地存储在两个单独的向量中。 (将键保留在向量中还可以提高缓存友好性,并减少分配开销。)

2)伪装为map<integer_type, T>vector<T> ,简化了与其他map<X, T>类型的互操作性。

3)通过压缩其他几个容器而形成的逻辑容器,产生一个逻辑value_type,它是对压缩容器的值类型的引用的tuple (在某些应用程序中,一个或多个压缩容器可以根据其他值或序列号进行整体计算。)

4)聚合类型的容器的视图,其中仅包含某些值。 (很可能底层容器和视图都是元组,其中视图元组的类型列表是底层容器类型的子集,可能以不同的顺序排列)。

我确信其他人可以轻松地添加到此列表中; 这些只是过去几个月来我以某种方式入侵的工具。

不要通过考虑“合格的容器”来限制自己:标准中没有什么依赖于一个容器。 将容器要求视为描述标准中定义的容器要求的简捷方式。 而已。 只要您的容器产生的迭代器是有效的,您就可以使用所有相应的算法,也可以使用您自己编写的算法。

最好的模型是std::vector< bool > 它尽可能接近合规性,但其迭代器确实会产生代理。

该标准甚至指定std::vector<bool>::reference是一个类。 但是容器要求表指定X::reference产生“ T的左值”。 因此,它是严格不合规的。

但是迭代器并不绑定到T 迭代器的value_type必须为Treference输入迭代器的要求, reference必须转换为value_type

正如皮特·贝克尔(Pete Becker)所提到的那样,需求表涵盖了相当广泛的范围,并且各个算法指定了它们的需求。 只有需要reference才能真正成为引用的算法才会中断,这只是显而易见的一种。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM