C++ 我可以将反向迭代器转换为正向迭代器吗?
我有一个名为C++ 我可以将反向迭代器转换为正向迭代器吗?,c++,iterator,C++,Iterator,我有一个名为Action的类,它本质上是一个围绕Move对象的包装器 因为我需要向前和向后遍历移动的deque,所以我有一个向前迭代器和一个反向迭代器作为类的成员变量。这样做的原因是因为我需要知道我什么时候已经过了德克的“终点”,无论是向前还是向后 该类如下所示: class Action { public: SetMoves(std::deque<Move> & dmoves) { _moves = dmoves; } void Advance();
Action
的类,它本质上是一个围绕Move
对象的包装器
因为我需要向前和向后遍历移动的deque,所以我有一个向前迭代器和一个反向迭代器作为类的成员变量。这样做的原因是因为我需要知道我什么时候已经过了德克的“终点”,无论是向前还是向后
该类如下所示:
class Action
{
public:
SetMoves(std::deque<Move> & dmoves) { _moves = dmoves; }
void Advance();
bool Finished()
{
if( bForward )
return (currentfwd==_moves.end());
else
return (currentbck==_moves.rend());
}
private:
std::deque<Move> _moves;
std::deque<Move>::const_iterator currentfwd;
std::deque<Move>::const_reverse_iterator currentbck;
bool bForward;
};
#include <iostream>
#include <vector>
#include <iterator>
int main() {
int i[] = { 1, 2, 3, 4};
std::vector<int> numbers(i, i+4);
std::cout << *numbers.rbegin() << "\n";
std::cout << *numbers.rbegin().base() << "\n";
std::cout << *(numbers.rbegin()+1).base() << "\n";
std::cout << *numbers.rend() << "\n";
std::cout << *numbers.rend().base() << "\n";
std::cout << *(numbers.rend()+1).base() << "\n";
}
我的问题是,我希望能够检索到当前Move
对象的迭代器,而不需要查询是向前还是向后。这意味着一个函数返回一种类型的迭代器,但我有两种类型
我是否应该忘记返回迭代器,而是返回对Move
对象的常量引用?也许您应该重新考虑容器的选择
通常,您不需要使用反向迭代器进行反向运算
currentfwd--
将倒退,尽管它可能不适用于(我假设您尝试过)出列
您真正应该做的是在这里将您的类建模为出列的装饰器,并实现您自己的动作迭代器。无论如何,我都会这样做。反向迭代器有一个成员,它返回一个相应的正向迭代器。请注意,此不是引用同一对象的迭代器-它实际上引用序列中的下一个对象。这是因为rbegin()
对应于end()
,rend()
对应于begin()
因此,如果您想返回一个迭代器,那么您可以执行以下操作
std::deque<Move>::const_iterator Current() const
{
if (forward)
return currentfwd;
else
return (currentbck+1).base();
}
std::deque::const\u迭代器Current()const
{
如果(转发)
返回电流fwd;
其他的
返回值(currentbck+1).base();
}
不过,我更愿意返回一个引用,并将所有迭代细节封装在类中。因为
是一个(与std::vector
相同)对于两次遍历,最好在deque中使用一个整数索引。在我看来,在同一个类中实际上有两种不同的行为
值得注意的是,您似乎只能按一个顺序遍历集合,否则,如果您开始遍历,然后更改b forward
参数,您将遇到非常奇怪的情况
就个人而言,我完全支持公开这两个迭代器(即,forwardbegin、end、rbegin和rend
)
您还可以返回一个简单的迭代器对象:
template <class T>
class Iterator
{
public:
typedef typename T::reference_type reference_type;
Iterator(T it, T end) : m_it(it), m_end(end) {}
operator bool() const { return m_it != m_end; }
reference_type operator*() const { return *m_it; }
Iterator& operator++() { ++m_it; return *this; }
private:
T m_it;
T m_end;
};
template <class T>
Iterator<T> make_iterator(T it, T end) { return Iterator<T>(it,end); }
模板
类迭代器
{
公众:
typedef typename T::reference_type reference_type;
迭代器(T it,T end):m_it(it),m_end(end){}
运算符bool()常量{返回m_it!=m_end;}
引用类型运算符*()常量{return*m_it;}
迭代器和运算符+++(){++m_it;返回*this;}
私人:
T m_it;
T m_end;
};
模板
迭代器使_迭代器(T it,T end){返回迭代器(it,end);}
然后,您只需返回以下简单对象:
class Action
{
public:
Action(std::deque<Move> const& d): m_deque(d) {} // const& please
typedef Iterator< std::deque<Move>::iterator > forward_iterator_type;
typedef Iterator< std::deque<Move>::reverse_iterator > backward_iterator_type;
forward_iterator_type forward_iterator()
{
return make_iterator(m_deque.begin(), m_deque.end());
}
backward_iterator_type backward_iterator()
{
return make_iterator(m_deque.rbegin(), m_deque.rend());
}
private:
std::deque<Move> m_deque;
};
集体诉讼
{
公众:
动作(std::deque const&d):m_deque(d){}//const&please
typedef迭代器forward\u Iterator\u type;
typedef迭代器backward_Iterator_type;
前向迭代器类型前向迭代器()
{
返回make_迭代器(m_deque.begin(),m_deque.end());
}
反向迭代器类型反向迭代器()
{
返回make_迭代器(m_deque.rbegin(),m_deque.rend());
}
私人:
std::deque m_deque;
};
或者,如果您想在正向和反向遍历之间动态选择,您可以将迭代器设置为纯虚拟接口,同时具有正向和反向遍历
但实际上,如果看起来您只会使用一个,那么我真的看不到同时存储正向和反向迭代器的意义:/这正是促使STL设计开始的那种问题。有真正的原因:不使用接受任意迭代器的算法将迭代器与容器一起存储 , 让算法一次计算整个范围,而不是单个项
我怀疑你现在看到的或多或少是真正问题的冰山一角。我的建议是退后一步,而不是询问如何处理当前设计的细节,而是询问一个更一般的问题,即您试图实现什么,以及如何最好地实现最终结果
对于那些主要关心标题中问题的人来说,答案是一个严格限定的“是”。特别是,反向迭代器有一个base()
成员来执行此操作。不过,这些条件有些问题
演示问题,考虑这样的代码:
class Action
{
public:
SetMoves(std::deque<Move> & dmoves) { _moves = dmoves; }
void Advance();
bool Finished()
{
if( bForward )
return (currentfwd==_moves.end());
else
return (currentbck==_moves.rend());
}
private:
std::deque<Move> _moves;
std::deque<Move>::const_iterator currentfwd;
std::deque<Move>::const_reverse_iterator currentbck;
bool bForward;
};
#include <iostream>
#include <vector>
#include <iterator>
int main() {
int i[] = { 1, 2, 3, 4};
std::vector<int> numbers(i, i+4);
std::cout << *numbers.rbegin() << "\n";
std::cout << *numbers.rbegin().base() << "\n";
std::cout << *(numbers.rbegin()+1).base() << "\n";
std::cout << *numbers.rend() << "\n";
std::cout << *numbers.rend().base() << "\n";
std::cout << *(numbers.rend()+1).base() << "\n";
}
摘要:对于rbegin()
我们必须在转换为正向迭代器之前添加一个迭代器,才能获得有效的迭代器——但是对于rend()
我们不能在转换为有效迭代器之前添加一个迭代器
只要您使用X.rbegin()
和X.rend()
作为泛型算法的参数,这很好——但经验表明,转换为正向迭代器通常会导致问题
然而,最后,对于问题的主体(与标题相反),答案与上面给出的基本相同:问题源于尝试创建一个对象,该对象将集合与两个迭代器组合到该集合中。如果解决了这个问题,那么使用正向和反向迭代器的整个业务将变得毫无意义。谢谢Charles。返回的问题是Finished()函数中的问题-当我在第一个元素前一个元素(即,已经超过了“rend()”)时,我需要知道。谢谢-我一直在应用程序的其余部分使用deque,正是出于这个原因。我不知道为什么我对迭代器有一种隧道式的看法:-)这就是w