最近,用户@Mooing Duck设计concatenated_range了一个优雅的自定义迭代器,解决了"链接"两个迭代器的问题.
它适用于它的预期用途:
auto range0=concatenate_ranges(x,x+i-1,x+i,x+a5+1);
a6=foo(range0.first,range0.second);
Run Code Online (Sandbox Code Playgroud)
现在,我想通过做(示例#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));
Run Code Online (Sandbox Code Playgroud)
毋庸置疑,编译器并不开心.另一种选择(不确定订购是否在这里):
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);
Run Code Online (Sandbox Code Playgroud)
不被认为是理所当然的:(.
我的问题是:我怎样才能适应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 << ' ';
}
Run Code Online (Sandbox Code Playgroud)
您正在reverse_iterator错误地实例化模板.尝试
auto fst = std::reverse_iterator<decltype(range0.second)>(range0.second);
auto snd = std::reverse_iterator<decltype(range0.first)>(range0.first);
Run Code Online (Sandbox Code Playgroud)
要使类型更明确:
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);
Run Code Online (Sandbox Code Playgroud)
我不想写下类似的东西std::pair<std::reverse_iterator<concatenated_range_iterator<std::vector<int>::iterator>>,std::reverse_iterator<concatenated_range_iterator<std::vector<int>::iterator>>>!
| 归档时间: |
|
| 查看次数: |
207 次 |
| 最近记录: |