为什么 std::move_iterator 在取消对右值引用的引用时可以将自己宣传为前向(或更强)迭代器?



根据 cpp 首选项,std::move_iterator将其::iterator_category设置为其底层迭代器1的类别。

但我认为它充其量只能是一个输入/输出迭代器,因为对于前向迭代器reference必须是左值引用,而move_iteratorreference(以及返回类型operator*)设置为右值引用2

这是对迭代器具有错误类别的公然错误标记吗?

能够为我自己的迭代器执行此操作无疑是方便的。如果即使是标准库也这样做,我有什么理由不应该这样做吗?


1但是任何比random_access_iterator_tag强的东西都会被截断为random_access_iterator_tag,这很奇怪,因为contiguous_iterator_tag应该只用于::iterator_concept

2或者,如果它不是引用,则保持原样,但底层迭代器也不应该将自己宣传为前向迭代器。

一方面,关于前向迭代器需求的 cpp偏好文章是错误的(已经被某人修复了)。reference必须是任何引用(&&&),而不是特定的左值引用(&)。意思是move_iterator确实符合。

但另一方面,自动确定::iterator_category使用不同的措辞,这只允许左值引用:

concept cpp17-forward-iterator = ... && is_lvalue_reference_v<iter_reference_t<I>>

这看起来像一个标准缺陷。我已经写信给lwgchair@gmail.com,等待回复。


前向迭代器能够使用任何类型的引用的来源:

[forward.iterators]/1.3

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

另见LWG1211(从2009年开始),它提出了同样的问题,并由N3066(2010年)解决,它将措辞从"左值参考"更改为"任何参考"。(感谢@康桓瑋的链接)。

最新更新