Her*_*ert 4 c++ stl c++11 reverse-iterator c++14
我创建了一个简单的不可变双向迭代器:
#include <iostream>
#include <memory>
#include <iterator>
#include <vector>
#include <algorithm>
class my_iterator : public std::iterator<std::bidirectional_iterator_tag, int
//, std::ptrdiff_t, int*, int
> {
int d_val;
public:
my_iterator() : d_val(0) {}
my_iterator(int val) : d_val(val) {}
my_iterator operator--(int) { d_val--; return my_iterator(d_val + 1); }
my_iterator &operator--() { d_val--; return *this; }
my_iterator operator++(int) { d_val++; return my_iterator(d_val - 1); }
my_iterator &operator++() { d_val++; return *this; }
int operator*() const { return d_val; }
bool operator==(my_iterator const &o) { return d_val == o.d_val; }
bool operator!=(my_iterator const &o) { return d_val != o.d_val ; }
};
int main() {
std::reverse_iterator<my_iterator> reverse_it_begin(25);
std::reverse_iterator<my_iterator> reverse_it_end(12);
std::for_each(reverse_it_begin, reverse_it_end, [](int e){ std::cout << e << ' '; });
std::cout << '\n';
}
Run Code Online (Sandbox Code Playgroud)
迭代器是不可变的,因为operator*()返回int而不是int引用.据我所知,这是可能的,因为迭代器是否符合BidirectionalIterator概念或者OutputIterator概念是正交的(所有4种组合都是可能的).
但是,下面的代码会导致编译时错误,即:
/usr/include/c++/4.9/bits/stl_iterator.h:164:9: error: invalid initialization of non-const reference of type 'std::reverse_iterator<my_iterator>::reference {aka int&}' from an rvalue of type 'int'
Run Code Online (Sandbox Code Playgroud)
完整背景:
In file included from /usr/include/c++/4.9/bits/stl_algobase.h:67:0,
from /usr/include/c++/4.9/bits/char_traits.h:39,
from /usr/include/c++/4.9/ios:40,
from /usr/include/c++/4.9/ostream:38,
from /usr/include/c++/4.9/iostream:39,
from prog.cpp:1:
/usr/include/c++/4.9/bits/stl_iterator.h: In instantiation of 'std::reverse_iterator<_Iterator>::reference std::reverse_iterator<_Iterator>::operator*() const [with _Iterator = my_iterator; std::reverse_iterator<_Iterator>::reference = int&]':
/usr/include/c++/4.9/bits/stl_algo.h:3755:6: required from '_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = std::reverse_iterator<my_iterator>; _Funct = main()::<lambda(int)>]'
prog.cpp:30:86: required from here
/usr/include/c++/4.9/bits/stl_iterator.h:164:9: error: invalid initialization of non-const reference of type 'std::reverse_iterator<my_iterator>::reference {aka int&}' from an rvalue of type 'int'
return *--__tmp;
^
Success time: 0 mem
Run Code Online (Sandbox Code Playgroud)
有关reverse_iterator和for_each状态的cppreference页面分别需要BidirectionalIterator和InputIterator.我认为这两个要求都得到满足,但是stl仍然为引用分配了一个取消引用的值.
为什么stl的for_each/reverse_iterator期望迭代器上的T&operator*()不需要是OutputIterator?
PS:注释行可以通过声明引用应该按值存储来修复问题,当然非常hacky.
它不需要OutputIterator.问题是你的代码违反了所有输入迭代器的基本要求*:*r必须返回reference**.您的代码定义my_iterator::reference为int &(由于std::iterator默认模板参数),但operator*返回一个int.
它reference实际上不是引用类型(istreambuf_iterator<charT>::reference例如,是charT)是有效的,但operator*必须返回reference.reverse_iterator依赖于它,因为它定义了它的reference成员,因此operator*它的包含迭代器的返回类型reference.
根据标准,对于前向迭代器或更强,reference必须是参考类型.但是标准本身就在于它调用vector<bool>::iterator随机访问迭代器(它operator*必须返回一个代理),而委员会显然计划对该array_view提议撒谎.因此,虽然制作my_iterator::reference int意味着它在技术上不再是双向迭代器,但实际上它可能会起作用.希望通过Concepts,我们可以获得比我们现有的更好,更细粒度的要求.
*关于输出迭代器的标准存在矛盾.见LWG问题2437.
**技术上,std::iterator_traits<It>::reference.对于类类型,iterator_traits默认情况下遵循成员typedef It::reference.
所有迭代器的迭代器要求都列在[iterator.iterators]中:

reference指的是typedef iterator_traits<my_iterator<..>>:
在以下部分中,
a和b表示类型的值X或const X,difference_type并且reference指的是类型iterator_traits<X>::difference_type和iterator_traits<X>::reference分别,[..]
由于主模板iterator_traits只是将typedef默认为模板参数本身中定义的类型,我们讨论的是referencetypedef my_iterator- 而且它是从base继承的std::iterator<...>,默认为T&.
你的operator*回报int虽然,但肯定不是int&.
取消注释你的行适用于InputIterators,因为它int可以转换为int:

但是对于ForwardIterators失败了 - [forward.iterators]/1:
类或指针类型
X满足前向迭代器的要求- 如果
X是一个可变的迭代器,reference是一个引用T; ifX是一个const迭代器,reference是一个引用const T,
| 归档时间: |
|
| 查看次数: |
453 次 |
| 最近记录: |