最近,用户@Mooing Duck设计了concatenated_range
,这是一个优雅的自定义迭代器,可以解决链接问题'两个迭代器,都在引擎盖下。
它的用途很有用:
auto range0=concatenate_ranges(x,x+i-1,x+i,x+a5+1);
a6=foo(range0.first,range0.second);
现在,我想通过做(示例#2)来适应它:
auto range0=concatenate_ranges(x+a5+1,x+i-1,x+i+1,x+n);
a6=foo(std::reverse_iterator<float*>(range0.second),std::reverse_iterator<float*>(range0.first));
毋庸置疑,编译器并不高兴。另一种选择(不确定订购是否正确):
auto range0=concatenate_ranges(std::reverse_iterator<float*>(x+n),x+i+1,x+i-1,std::reverse_iterator<float*>(x+a5[i]+1));
a6=foo(range0.first,range0.second);
不是理所当然的:(。
我的问题是:我如何调整concatenate_ranges()
以便它的输出可以
馈入std::reverse_iterator
(如上面的第二个例子)。另外,我不介意
使用boost::
如果它让事情变得更容易。
用户@Jack报告原始答案中的链接没有显示他的代码。我不知道这个问题有多广泛,所以为了清楚起见,我重现了我在这里提到的代码(请参阅原始答案的解释):
#include <boost/iterator/iterator_facade.hpp>
#include <iterator>
#include <cassert>
template<class base>
class concatenated_range_iterator
: public boost::iterator_facade<
concatenated_range_iterator<base>,
typename std::iterator_traits<base>::value_type,
typename std::iterator_traits<base>::iterator_category,
typename std::iterator_traits<base>::reference,
typename std::iterator_traits<base>::difference_type
>
{
public:
typedef typename std::iterator_traits<base>::iterator_category iterator_category;
typedef typename std::iterator_traits<base>::value_type value_type;
typedef typename std::iterator_traits<base>::difference_type difference_type;
typedef typename std::iterator_traits<base>::pointer pointer;
typedef typename std::iterator_traits<base>::reference reference;
concatenated_range_iterator() = default;
concatenated_range_iterator(bool begin, base begin1, base end1, base begin2, base end2)
:current(begin?begin1:end2), end_first(end1), begin_second(begin2), in_first(begin)
{}
reference dereference() {return *current;}
reference dereference() const {return *current;}
bool equal(const concatenated_range_iterator& rhs) const {
assert(end_first==rhs.end_first);
assert(begin_second==rhs.begin_second);
return in_first==rhs.in_first && current==rhs.current;
}
void increment() {
++current;
if (in_first) {
if (current==end_first) {
current = begin_second;
in_first = false;
}
}
}
void decrement() {
if (!in_first) {
if (current==begin_second) {
current = end_first;
in_first = true;
}
}
--current;
}
void advance(difference_type n) {
if (n>=0) {
if (in_first) {
difference_type safe = end_first-current;
if (safe <= n) {
current = begin_second;
n -= safe;
in_first = false;
}
}
} else {
if (!in_first) {
difference_type safe = current-begin_second;
if (safe <= n) {
current = end_first;
n += safe;
in_first = true;
}
}
}
current += n;
}
difference_type distance_to(const concatenated_range_iterator& rhs) const {
assert(end_first==rhs.end_first);
assert(begin_second==rhs.begin_second);
if (in_first) {
if (rhs.in_first)
return rhs.current-current;
else
return rhs.current-begin_second + end_first-current;
} else {
if (rhs.in_first)
return rhs.current-end_first + begin_second-current;
else
return rhs.current-current;
}
}
protected:
base current;
base end_first;
base begin_second;
bool in_first;
};
template<class base>
std::pair<concatenated_range_iterator<base>,concatenated_range_iterator<base>>
concatenate_ranges(base first1, base end1, base first2, base end2)
{
return std::pair<concatenated_range_iterator<base>,concatenated_range_iterator<base>>(
concatenated_range_iterator<base>(true, first1, end1, first2, end2),
concatenated_range_iterator<base>(false, first1, end1, first2, end2)
);
}
#include <vector>
#include <iostream>
int main() {
std::vector<int> vars = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
auto range = concatenate_ranges(vars.begin(), vars.begin()+4, vars.begin()+5, vars.end());
for(auto iter=range.first; iter!=range.second; ++iter)
std::cout << *iter << ' ';
}
答案 0 :(得分:5)
您正在错误地实例化reverse_iterator
模板。尝试
auto fst = std::reverse_iterator<decltype(range0.second)>(range0.second);
auto snd = std::reverse_iterator<decltype(range0.first)>(range0.first);
使类型更明确:
typedef std::vector<int>::iterator VI;
typedef concatenated_range_iterator<VI> CRVI;
typedef std::pair<CRVI, CRVI> CRVIrange;
CRVIrange range0 = concatenate_ranges(vars.begin(), vars.begin()+2,
vars.begin()+5, vars.end());
typedef std::reverse_iterator<CRVI> RCRVI;
RCRVI fst = RCRVI(range0.second);
RCRVI snd = RCRVI(range0.first);
我不想写下像std::pair<std::reverse_iterator<concatenated_range_iterator<std::vector<int>::iterator>>,std::reverse_iterator<concatenated_range_iterator<std::vector<int>::iterator>>>
!