创建Iterator到C ++容器,返回一个std :: pair

时间:2013-10-29 10:43:20

标签: c++ iterator

我正在尝试在C ++中实现一个容器,该容器使用一个平面数组来存储数据,但是成对地迭代这些数据。现在我可以轻松地更改实现,使容器保存std::pair的向量,但是我想从元素0或元素1开始迭代对。

为了说明我想要实现的目标,如果我的底层数组如下: 1,2,3,4,5,6,7,8-

我想定义两个迭代器,一个返回对: (1,2),(3,4),(5,6),(7,8) 和返回对的第二个迭代器: (2,3),(4,5),(6,7)

是否可以这样做,同时仍允许迭代器的元素作为底层数组的引用?

3 个答案:

答案 0 :(得分:3)

可以编写自己的迭代器,迭代元素。以下问题显示了如何完成的一些解释: Custom Iterator in C++

然后,您可以将所需的值作为std :: pair返回并迭代到下一个元素对(通过将计数器递增2)。

答案 1 :(得分:2)

Boost库有Iterator Adaptor,允许您包装其他迭代器类型并更改或调整其功能。以下是您如何将它用于您的目的:

#include <boost/iterator/iterator_adaptor.hpp>
#include <vector>

struct iterator :
    public boost::iterator_adaptor<
        iterator,                    // the name of our class, see docs for details
        std::vector<int>::iterator,  // underlying base iterator
        std::pair<int&, int&>,       // our value type
        boost::forward_traversal_tag // the category you wish to give it
    >
{
     // need this to convert from vector::iterator to ours
    explicit iterator(std::vector<int>::iterator i)
        : iterator::iterator_adaptor_(i) {}

    value_type operator*()
    {
        return value_type(
            *base_reference(),
            *(base_reference()+1)
        );
    }
};

使用示例:

std::vector<int> v {1,2,3,4};
iterator it(v.begin());
++it;
(*it).first = 0;  // TODO: operator->
(*it).second = 0;

for (int i : v) std::cout << i << ' '; // prints 1 0 0 4

您还需要覆盖比较以正确处理结束条件等。希望有所帮助。

答案 2 :(得分:0)

以为我会在我的代码中添加实际使用的内容。我不想按照@jrok的建议使用boost,但是他们的回答中的类型std::pair<int&, int&>给了我一些所需的提示。

下面是我构建的使用两个迭代器的类。一个RepeatIterator返回从基础数据中的偶数索引开始的对,以及一个返回从奇数索引开始的对的SpacerIterator

class RepeatArray {
    typedef std::vector<int> storage_t;

public:
    class RepeatIterator {
    public:
        typedef RepeatIterator self_t;
        typedef int value_t;
        typedef int& reference_t;
        typedef int* pointer_t;
        typedef std::pair<reference_t, reference_t> return_t;

        RepeatIterator(storage_t::iterator input) : current_pos(input){}

        return_t operator *() {
            return return_t(*(current_pos), *(current_pos + 1 ));
        }

        self_t operator++() { self_t i = *this; current_pos += 2; return i; }
        self_t operator++(int junk) { current_pos+=2; return *this; }


        bool operator==(const self_t& rhs) { return current_pos == rhs.current_pos; }
        bool operator!=(const self_t& rhs) { return current_pos != rhs.current_pos; }
        bool operator<(const self_t& rhs) { return current_pos < rhs.current_pos; }
        bool operator<=(const self_t& rhs) { return current_pos <= rhs.current_pos; }
        bool operator>(const self_t& rhs) { return current_pos > rhs.current_pos; }
        bool operator>=(const self_t& rhs) { return current_pos >= rhs.current_pos; }

    private:
        storage_t::iterator current_pos;
    };

    class SpacerIterator {
    public:
        typedef SpacerIterator self_t;
        typedef int value_t;
        typedef int& reference_t;
        typedef int* pointer_t;
        typedef std::pair<reference_t, reference_t> return_t;

        SpacerIterator(storage_t::iterator input) : current_pos(input){}

        return_t operator *() {
            return return_t(*(current_pos), *(current_pos + 1 ));
        }

        self_t operator++() { self_t i = *this; current_pos += 2; return i; }
        self_t operator++(int junk) { current_pos+=2; return *this; }

        bool operator==(const self_t& rhs) { return current_pos == rhs.current_pos; }
        bool operator!=(const self_t& rhs) { return current_pos != rhs.current_pos; }
        bool operator<(const self_t& rhs) { return current_pos < rhs.current_pos; }
        bool operator<=(const self_t& rhs) { return current_pos <= rhs.current_pos; }
        bool operator>(const self_t& rhs) { return current_pos > rhs.current_pos; }
        bool operator>=(const self_t& rhs) { return current_pos >= rhs.current_pos; }


    private:
        storage_t::iterator current_pos;
    };

    void add(int start, int end) {
        positions.push_back(start);
        positions.push_back(end);
    }

    void dump() {
        for (auto i : positions) {
            std::cout <<i<<",";
        }
        std::cout <<std::endl;
    }

    RepeatIterator repeatBegin(){return RepeatIterator(positions.begin());}
    RepeatIterator repeatEnd(){return RepeatIterator(positions.end());}

    SpacerIterator spacerBegin(){return SpacerIterator(positions.begin() + 1);}
    SpacerIterator spacerEnd(){return SpacerIterator(positions.end() - 1);}

protected:
    storage_t positions;
};

然后使用clang++ -std=c++0x -o testRepeatArray RepeatArray.cpp

编译测试程序
int main() {
    RepeatArray r = RepeatArray();
    r.add(1,3);
    r.add(7,12);
    std::cout<<"original:"<<std::endl;
    r.dump();

    std::cout << "Testing Repeat iterator:"<<std::endl;
    for (RepeatArray::RepeatIterator it2 = r.repeatBegin(); it2 != r.repeatEnd(); ++it2) {
        std::cout << (*it2).first <<","<< (*it2).second << std::endl;
    }
    std::cout << "Testing Spacer iterator:"<<std::endl;
    for (RepeatArray::SpacerIterator it3 = r.spacerBegin(); it3 != r.spacerEnd(); ++it3) {
        std::cout << (*it3).first <<","<< (*it3).second << std::endl;
    }

    std::cout<<"Testing modification:"<<std::endl;

    RepeatArray::RepeatIterator it = r.repeatBegin();
    (*it).first = 0;
    (*it).second = 123;

    r.dump();
    return 0;
}