我可以将反向迭代器转换为前向迭代器吗? [英] Can I convert a reverse iterator to a forward iterator?

查看:89
本文介绍了我可以将反向迭代器转换为前向迭代器吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 Action 的类,它本质上是一个包含 Move p>

因为我需要向前和向后遍历 Moves 的deque,我有一个forward iterator和一个reverse_iterator作为成员类的变量。这是因为我需要知道,当我走过一个过去的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;
};

Advance 函数如下: / p>

  void Action :: Advance 
{
if(bForward)
currentfwd ++;
else
currentbck ++;
}

我的问题是,我想能够检索迭代器到当前移动对象,而不需要查询我是向前还是向后。这意味着一个函数返回一种类型的迭代器,但我有两种类型。



我应该忘记返回一个迭代器,并且返回一个const引用到 Move



最好的祝福,



BeeBand

解决方案

这是确切提示STL设计开始的问题。

  • 使用接受任意迭代器的算法
  • 使用算法评估整个范围而不是单个项目a time



    我怀疑你现在看到的是或多或少的真正问题的冰山一角。我的建议是退一步,而不是问如何处理设计的细节,因为它目前的情况,请问一个更一般的问题,你想要完成什么,以及如何最好地完成



    对于那些主要关心标题中问题的人,答案是一个高度合格的是。特别是,reverse_iterator有一个 base()成员。资格有点问题。



    演示问题,请考虑这样的代码:

      include< iostream> 
    #include< vector>
    #include< iterator>

    int main(){
    int i [] = {1,2,3,4};
    std :: vector< int>数字(i,i + 4);

    std :: cout<< * numbers.rbegin()<< \\\
    ;
    std :: cout<< * numbers.rbegin()。base()<< \\\
    ;
    std :: cout<< *(numbers.rbegin()+ 1).base()< \\\
    ;

    std :: cout<< * numbers.rend()<< \\\
    ;
    std :: cout<< * numbers.rend()。base()<< \\\
    ;
    std :: cout<< *(numbers.rend()+ 1).base()< \\\
    ;
    }

    在我的特定机器上运行此特定时刻会产生以下输出: / p>

      4 
    0
    4
    -1879048016
    1
    - 1879048016

    摘要:与 rbegin() 必须在转换为前向迭代器之前添加一个迭代器以获得有效的迭代器,但 rend()



    只要你使用 X.rbegin() X.rend()作为一个通用算法的参数,这很好 - 但经验表明,转换为正向迭代器往往会导致问题。



    然而,最后,对于问题的主体(而不是标题),答案几乎如上所述:问题源于尝试创建一个对象将集合与一些迭代器结合到集合中。解决这个问题,整个业务与正向和反向迭代器变得哑巴。


    I have a class called Action, which is essentially a wrapper around a deque of Move objects.

    Because I need to traverse the deque of Moves both forward and backwards, I have a forward iterator and a reverse_iterator as member variables of the class. The reason for this is becuase I need to know when I have gone one past the "end" of the deque, both when I am going forwards or backwards.

    The class looks like this:

    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;
    };
    

    The Advance function is as follows:

    void Action::Advance
    {
        if( bForward)
            currentfwd++;
        else
            currentbck++;
    }
    

    My problem is, I want to be able to retrieve an iterator to the current Move object, without needing to query whether I am going forwards or backwards. This means one function returning one type of iterator, but I have two types.

    Should I forget returning an iterator, and return a const reference to a Move object instead?

    best wishes,

    BeeBand

    解决方案

    This is exactly the sort of problem that prompted the design of STL to start with. There are real reasons for:

    1. Not storing iterators along with containers
    2. Using algorithms that accept arbitrary iterators
    3. Having algorithms evaluate an entire range instead of a single item at a time

    I suspect what you're seeing right now is more or less the tip of the iceberg of the real problems. My advice would be to take a step back, and instead of asking about how to deal with the details of the design as it currently stands, ask a somewhat more general question about what you're trying to accomplish, and how best to accomplish that end result.

    For those who care primarily about the question in the title, the answer is a heavily qualified "yes". In particular, a reverse_iterator has a base() member to do that. The qualifications are somewhat problematic though.

    The demonstrate the problem, consider code like this:

    #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";
    }
    

    Running this at this particular moment on my particular machine produces the following output:

    4
    0
    4
    -1879048016
    1
    -1879048016
    

    Summary: with rbegin() we must add one before converting to a forward iterator to get an iterator that's valid -- but with rend() we must not add one before converting to get a valid iterator.

    As long as you're using X.rbegin() and X.rend() as the parameters to a generic algorithm, that's fine--but experience indicates that converting to forward iterators often leads to problems.

    In the end, however, for the body of the question (as opposed to the title), the answer is pretty much as given above: the problem stems from trying to create an object that combines the collection with a couple of iterators into that collection. Fix that problem, and the whole business with forward and reverse iterators becomes moot.

    这篇关于我可以将反向迭代器转换为前向迭代器吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆