C++ 平坦迭代器

C++ 平坦迭代器,c++,c++11,iterator,std,C++,C++11,Iterator,Std,是否有任何现有的迭代器实现(可能在boost中)实现某种平坦迭代器 例如: unordered_set<vector<int> > s; s.insert(vector<int>()); s.insert({1,2,3,4,5}); s.insert({6,7,8}); s.insert({9,10,11,12}); flattening_iterator<unordered_set<vector<int> >::iterat

是否有任何现有的迭代器实现(可能在boost中)实现某种平坦迭代器

例如:

unordered_set<vector<int> > s;

s.insert(vector<int>());
s.insert({1,2,3,4,5});
s.insert({6,7,8});
s.insert({9,10,11,12});

flattening_iterator<unordered_set<vector<int> >::iterator> it( ... ), end( ... );
for(; it != end; ++it)
{
    cout << *it << endl;
}
//would print the numbers 1 through 12
无序的集合;
s、 插入(向量());
s、 插入({1,2,3,4,5});
s、 插入({6,7,8});
s、 插入({9,10,11,12});
展平迭代器it(…),end(…);
for(;it!=end;++it)
{

cout您可以在boost中使用迭代器facade创建一个

我编写了迭代器产品,您可以将其用作模板:

我不知道大型库中有任何实现,但它看起来是一个有趣的问题,因此我编写了一个基本实现。我只使用我在这里介绍的测试用例对其进行了测试,因此我不建议在没有进一步测试的情况下使用它

这个问题比看起来更棘手,因为一些“内部”容器可能是空的,您必须跳过它们。这意味着将
展平\u迭代器推进一个位置实际上可能会将迭代器推进到“外部”容器由多个位置移动。因此,
展平迭代器
需要知道外部范围的结束位置,以便知道何时需要停止

此实现是一个正向迭代器。双向迭代器还需要跟踪外部范围的开始。使用
flatten
函数模板可以使构造
flatten\u迭代器变得更容易

#include <iterator>

// A forward iterator that "flattens" a container of containers.  For example,
// a vector<vector<int>> containing { { 1, 2, 3 }, { 4, 5, 6 } } is iterated as
// a single range, { 1, 2, 3, 4, 5, 6 }.
template <typename OuterIterator>
class flattening_iterator
{
public:

    typedef OuterIterator                                outer_iterator;
    typedef typename OuterIterator::value_type::iterator inner_iterator;

    typedef std::forward_iterator_tag                iterator_category;
    typedef typename inner_iterator::value_type      value_type;
    typedef typename inner_iterator::difference_type difference_type;
    typedef typename inner_iterator::pointer         pointer;
    typedef typename inner_iterator::reference       reference;

    flattening_iterator() { }
    flattening_iterator(outer_iterator it) : outer_it_(it), outer_end_(it) { }
    flattening_iterator(outer_iterator it, outer_iterator end) 
        : outer_it_(it), 
          outer_end_(end)
    { 
        if (outer_it_ == outer_end_) { return; }

        inner_it_ = outer_it_->begin();
        advance_past_empty_inner_containers();
    }

    reference operator*()  const { return *inner_it_;  }
    pointer   operator->() const { return &*inner_it_; }

    flattening_iterator& operator++()
    {
        ++inner_it_;
        if (inner_it_ == outer_it_->end())
            advance_past_empty_inner_containers();
        return *this;
    }

    flattening_iterator operator++(int)
    {
        flattening_iterator it(*this);
        ++*this;
        return it;
    }

    friend bool operator==(const flattening_iterator& a, 
                           const flattening_iterator& b)
    {
        if (a.outer_it_ != b.outer_it_)
            return false;

        if (a.outer_it_ != a.outer_end_ && 
            b.outer_it_ != b.outer_end_ &&
            a.inner_it_ != b.inner_it_)
            return false;

        return true;
    }

    friend bool operator!=(const flattening_iterator& a,
                           const flattening_iterator& b)
    {
        return !(a == b);
    }

private:

    void advance_past_empty_inner_containers()
    {
        while (outer_it_ != outer_end_ && inner_it_ == outer_it_->end())
        {
            ++outer_it_;
            if (outer_it_ != outer_end_) 
                inner_it_ = outer_it_->begin();
        }
    }

    outer_iterator outer_it_;
    outer_iterator outer_end_;
    inner_iterator inner_it_;
};

template <typename Iterator>
flattening_iterator<Iterator> flatten(Iterator it)
{
    return flattening_iterator<Iterator>(it, it);
}

template <typename Iterator>
flattening_iterator<Iterator> flatten(Iterator first, Iterator last)
{
    return flattening_iterator<Iterator>(first, last);
}
#包括
//前向迭代器,用于“展平”一个容器容器。例如,
//包含{1,2,3},{4,5,6}的向量被迭代为
//单个范围,{1,2,3,4,5,6}。
模板
类平坦迭代器
{
公众:
typedef外部迭代器外部迭代器;
typedef typename外部迭代器::值\类型::迭代器内部迭代器;
typedef std::forward_iterator_tag iterator_category;
typedef typename内部迭代器::值\类型值\类型;
typedef typename内部迭代器::差分类型差分类型;
typedef typename内部迭代器::指针;
typedef typename内部迭代器::reference;
展平_迭代器(){}
展平迭代器(外部迭代器it):外部迭代器it(it),外部迭代器end(it){
展平迭代器(外部迭代器it,外部迭代器end)
:外部_it_(it),
外端(端)
{ 
if(outer_it_==outer_end_){return;}
内部的=外部的->开始();
通过空的内部容器前进();
}
引用运算符*()常量{return*internal_it_;}
指针运算符->()常量{return&*internal_it_;}
平坦化_迭代器和运算符++()
{
++内心世界;
如果(内部\u it==外部\u it->end())
通过空的内部容器前进();
归还*这个;
}
展平迭代器运算符++(int)
{
展平迭代器it(*this);
++*这,;
归还它;
}
friend bool运算符==(常数展平迭代器&a,
常数展平(迭代器&b)
{
如果(a.outer\u it!=b.outer\u it)
返回false;
如果(a.outer\u it!=a.outer\u end&&
b、 外端&&
a、 内部的,内部的
返回false;
返回true;
}
friend bool运算符!=(常数展平\u迭代器&a,
常数展平(迭代器&b)
{
返回!(a==b);
}
私人:
无效前进\超过\空\内部\容器()
{
while(outer\u it!=outer\u end\u&&inner\u it\u==outer\u it->end())
{
++外部(it);;
如果(外部→它→外部→结束)
内部的=外部的->开始();
}
}
外部迭代器外部迭代器;
外部迭代器外部结束;
内部迭代器内部迭代器;
};
模板
展平\u迭代器展平(迭代器it)
{
返回平坦迭代器(it,it);
}
模板
展平\u迭代器展平(迭代器优先,迭代器最后)
{
返回平坦迭代器(第一个,最后一个);
}
以下是最小测试存根:

#include <algorithm>
#include <iostream>
#include <set>
#include <vector>

int main()
{
    // Generate some test data:  it looks like this:
    // { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 } }
    std::vector<std::vector<int>> v(3);
    int i(0);
    for (auto it(v.begin()); it != v.end(); ++it)
    {
        it->push_back(i++); it->push_back(i++);
        it->push_back(i++); it->push_back(i++);
    }

    // Flatten the data and print all the elements:
    for (auto it(flatten(v.begin(), v.end())); it != v.end(); ++it)
    {
        std::cout << *it << ", ";
    }
    std::cout << "\n";

    // Or, since the standard library algorithms are awesome:
    std::copy(flatten(v.begin(), v.end()), flatten(v.end()), 
              std::ostream_iterator<int>(std::cout, ", "));
}
#包括
#包括
#包括
#包括
int main()
{
//生成一些测试数据:如下所示:
// { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 } }
std::向量v(3);
int i(0);
for(自动启动(v.begin());it!=v.end();+it)
{
it->push_back(i++);it->push_back(i++);
it->push_back(i++);it->push_back(i++);
}
//展平数据并打印所有元素:
用于(自动调整(展平(v.begin(),v.end());调整!=v.end();+it)
{
std::cout我决定对展平迭代器的概念“改进”一点,尽管正如James所指出的,您一直在使用范围(除了最里面的容器),所以我只是通过使用范围和通过,从而获得了具有任意深度的展平范围

首先,我用了一块建筑砖:

template <typename C>
struct iterator { using type = typename C::iterator; };

template <typename C>
struct iterator<C const> { using type = typename C::const_iterator; };
这是我们这里的建筑砖,但事实上,我们可以用剩下的:

template <typename C, size_t N>
class FlattenedForwardRange {
    using Iter = typename iterator<C>::type;
    using Inner = FlattenedForwardRange<typename std::iterator_traits<Iter>::value_type, N-1>;
public:
    using pointer = typename Inner::pointer;
    using reference = typename Inner::reference;
    using value_type = typename Inner::value_type;

    FlattenedForwardRange(): _outer(), _inner() {}

    explicit FlattenedForwardRange(C& outer): _outer(outer), _inner() {
        if (not _outer) { return; }
        _inner = Inner{*_outer};
        this->advance();
    }

    // Observers
    explicit operator bool() const { return static_cast<bool>(_outer); }

    reference operator*() const { assert(*this); return *_inner; }
    pointer operator->() const { assert(*this); return _inner.operator->(); }

    // Modifiers
    FlattenedForwardRange& operator++() { ++_inner; this->advance(); return *this; }
    FlattenedForwardRange operator++(int) { FlattenedForwardRange tmp(*this); ++*this; return tmp; }

private:
    void advance() {
        if (_inner) { return; }

        for (++_outer; _outer; ++_outer) {
            _inner = Inner{*_outer};
            if (_inner) { return; }
        }
        _inner = Inner{};
    }

    ForwardRange<C> _outer;
    Inner _inner;
}; // class FlattenedForwardRange

template <typename C>
class FlattenedForwardRange<C, 0> {
    using Iter = typename iterator<C>::type;
public:
    using pointer = typename std::iterator_traits<Iter>::pointer;
    using reference = typename std::iterator_traits<Iter>::reference;
    using value_type = typename std::iterator_traits<Iter>::value_type;

    FlattenedForwardRange(): _range() {}

    explicit FlattenedForwardRange(C& c): _range(c) {}

    // Observers
    explicit operator bool() const { return static_cast<bool>(_range); }

    reference operator*() const { return *_range; }
    pointer operator->() const { return _range.operator->(); }

    // Modifiers
    FlattenedForwardRange& operator++() { ++_range; return *this; }
    FlattenedForwardRange operator++(int) { FlattenedForwardRange tmp(*this); ++*this; return tmp; }

private:
    ForwardRange<C> _range;
}; // class FlattenedForwardRange
模板
类展平ForwardRange{
使用Iter=typename迭代器::type;
使用内部=展平ForwardRange;
公众:
使用pointer=typename内部::指针;
使用reference=typename内部::reference;
使用value\u type=typename内部::value\u type;
FlattedForwardRange():_外部(),_内部(){}
显式FlattedForwardRange(C和外部):\u外部(外部),\u内部(){
如果(不在外){return;}
_内部=内部{*\u外部};
这个->前进();
}
//观察员
显式运算符bool()const{return static_cast(_outer);}
引用运算符*()常量{assert(*this);返回*_inner;}
指针运算符->()常量{assert(*this);返回_internal.operator->();}
//修饰语
FlattedForwardRange&operator++(){++_inner;this->advance();return*this;}
FlattedForwardRange运算符++(int){FlattedForwardRange tmp(*this);++*this;返回tmp;}
私人:
作废预付款(){
template <typename C, size_t N>
class FlattenedForwardRange {
    using Iter = typename iterator<C>::type;
    using Inner = FlattenedForwardRange<typename std::iterator_traits<Iter>::value_type, N-1>;
public:
    using pointer = typename Inner::pointer;
    using reference = typename Inner::reference;
    using value_type = typename Inner::value_type;

    FlattenedForwardRange(): _outer(), _inner() {}

    explicit FlattenedForwardRange(C& outer): _outer(outer), _inner() {
        if (not _outer) { return; }
        _inner = Inner{*_outer};
        this->advance();
    }

    // Observers
    explicit operator bool() const { return static_cast<bool>(_outer); }

    reference operator*() const { assert(*this); return *_inner; }
    pointer operator->() const { assert(*this); return _inner.operator->(); }

    // Modifiers
    FlattenedForwardRange& operator++() { ++_inner; this->advance(); return *this; }
    FlattenedForwardRange operator++(int) { FlattenedForwardRange tmp(*this); ++*this; return tmp; }

private:
    void advance() {
        if (_inner) { return; }

        for (++_outer; _outer; ++_outer) {
            _inner = Inner{*_outer};
            if (_inner) { return; }
        }
        _inner = Inner{};
    }

    ForwardRange<C> _outer;
    Inner _inner;
}; // class FlattenedForwardRange

template <typename C>
class FlattenedForwardRange<C, 0> {
    using Iter = typename iterator<C>::type;
public:
    using pointer = typename std::iterator_traits<Iter>::pointer;
    using reference = typename std::iterator_traits<Iter>::reference;
    using value_type = typename std::iterator_traits<Iter>::value_type;

    FlattenedForwardRange(): _range() {}

    explicit FlattenedForwardRange(C& c): _range(c) {}

    // Observers
    explicit operator bool() const { return static_cast<bool>(_range); }

    reference operator*() const { return *_range; }
    pointer operator->() const { return _range.operator->(); }

    // Modifiers
    FlattenedForwardRange& operator++() { ++_range; return *this; }
    FlattenedForwardRange operator++(int) { FlattenedForwardRange tmp(*this); ++*this; return tmp; }

private:
    ForwardRange<C> _range;
}; // class FlattenedForwardRange
#include "multidim.hpp"

// ... create "s" as in your example ...

auto view = multidim::makeFlatView(s);
// view offers now a flattened view on s

// You can now use iterators...
for (auto it = begin(view); it != end(view); ++it) cout << *it << endl;

// or a simple range-for loop
for (auto value : view) cout << value;