![](/img/trans.png)
[英]Why can an rvalue not bind to a non-const lvalue reference, other than the fact that writing to a temporary has no effect?
[英]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
(其中a
为X
类型)的要求。 要求是:
表107中的表(输入迭代器)
*a
如果a
是不可引用的,则a
必须“可转换为T”。来自表106(迭代器)中的
*r
必须具有类型reference
,其中r
为X&
类型X&
并且是可取消引用的。
但是,表106还指定++r
返回X&
,因此*++r
必须是reference
。 此外,(按照表107), *a++
必须是reference
,尽管(表109) a[n]
仅需要“可转换为参考”。 我得说,我看不出*a
,其中a
是类型的X
和*r
其中, r
是类型的X&
可能是不同的,但也许我错过了一些微妙。
也许这里有个小摆动间,但不多。 在某个时候,如果容器中实际上没有T
,则需要准备创建T
,以便您可以提供对其的引用。
但关键是
第24.2.5节,第 6(
a
和b
是类型X
值):如果a
和b
都是可引用的,则当且仅当*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
必须为T
并reference
输入迭代器的要求, reference
必须转换为value_type
。
正如皮特·贝克尔(Pete Becker)所提到的那样,需求表涵盖了相当广泛的范围,并且各个算法指定了它们的需求。 只有需要reference
才能真正成为引用的算法才会中断,这只是显而易见的一种。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.