Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何展平嵌套容器的迭代器?_C++_Iterator - Fatal编程技术网

C++ 如何展平嵌套容器的迭代器?

C++ 如何展平嵌套容器的迭代器?,c++,iterator,C++,Iterator,这是詹姆斯对这个问题的另一个后续回答: 如何更改Flattig_迭代器,使其递归工作?假设我有更多级别的嵌套容器,我不想被限制在给定的嵌套深度。也就是说,平坦化迭代器应该与 std::vector< std::vector < std::vector < int > > > std::vector

这是詹姆斯对这个问题的另一个后续回答:

如何更改Flattig_迭代器,使其递归工作?假设我有更多级别的嵌套容器,我不想被限制在给定的嵌套深度。也就是说,平坦化迭代器应该与

std::vector< std::vector < std::vector < int > > >
std::vector>
以及

std::vector< std::vector < std::vector < std::vector < int > > > >
std::vector>>
在我的实际代码中,我有一个对象数组,这些对象本身可能包含也可能不包含这样的数组

编辑

在使用不同的方法迭代不同类型的嵌套容器之后,我学到了一些其他人可能也感兴趣的东西:

使用嵌套循环访问容器元素的速度比使用迭代器解决方案快5到6倍

优点:

  • 元素可以是复杂的对象,例如(就像在我的例子中)包含容器的类
  • 更快的执行
缺点:

  • 每个容器结构都需要循环的新实现
  • 标准库算法不可用

其他利弊

我将快速概述一个解决方案:

  • 编写
    是一个容器
    特征,它检测
    begin()
    end()
    成员,或者可能检测一些更复杂的规则
  • 编写一个
    all_flatting_迭代器
    模板,它只是一个
    flatting_迭代器
  • T
    不是仅仅是常规迭代器的容器(使用默认模板
    bool
    参数)时,编写
    all\u flatting\u迭代器的专门化

  • 好的,所以这不是一个完整的解决方案-但我没有时间了。因此,它目前实现的不是一个完整的迭代器,而是一个简化的迭代器类,它定义了类似于这个接口的东西,并且需要C++11。我已经在g++4.7上对其进行了测试:

    template<typename NestedContainerType, typename Terminator>
    class flatten_iterator
    {
        bool complete();
        void advance();
        Terminator& current();
    };
    
    通过以下测试用例,它实现了您所期望的功能:

    int main( int argc, char* argv[] )
    {   
        typedef std::vector<int> n1_t;
        typedef std::vector<std::deque<short> > n2_t;
        typedef std::list<std::vector<std::vector<std::vector<double> > > > n4_t;
        typedef std::vector<std::deque<std::vector<std::deque<std::vector<std::list<float> > > > > > n6_t;
        
        n1_t n1 = { 1, 2, 3, 4 };
        n2_t n2 = { {}, { 1, 2 }, {3}, {}, {4}, {}, {} };
        n4_t n4 = { { { {1.0}, {},  {}, {2.0}, {} }, { {}, {} }, { {3.0} } }, { { { 4.0 } } } };
        n6_t n6 = { { { { { {1.0f}, {},  {}, {2.0f}, {} }, { {}, {} }, { {3.0f} } }, { { { 4.0f } } } } } };
        
        flatten_iterator<n1_t, int> i1( n1 );
        while ( !i1.complete() )
        {
            std::cout << i1.current() << std::endl;
            i1.advance();
        }
        
        flatten_iterator<n2_t, short> i2( n2 );
        while ( !i2.complete() )
        {
            std::cout << i2.current() << std::endl;
            i2.advance();
        }
        
        flatten_iterator<n4_t, double> i4( n4 );
        while ( !i4.complete() )
        {
            std::cout << i4.current() << std::endl;
            i4.advance();
        }
        
        flatten_iterator<n6_t, float> i6( n6 );
        while ( !i6.complete() )
        {
            std::cout << i6.current() << std::endl;
            i6.advance();
        }
    }
    

    请注意,它还不能与
    set
    s一起使用,因为需要一些foo来处理
    set
    迭代器返回常量引用这一事实。读者练习…:-)

    我来这里晚了一点,但我刚刚发表了一篇文章来解决这个问题。查看详细信息


    我的解决方案的灵感来自于使用“伸缩嵌套”迭代器。它增加了一些功能(例如,支持只读容器,如
    set
    s、向后迭代、随机访问),并提供了一个更令人愉快的界面,因为它可以自动检测“叶子”的类型元素。

    可能可变模板可以提供一种更方便的方法来使用建议的
    is_容器
    元函数。@xtofl可变模板在这里有什么帮助?只涉及一个模板参数。我梦想着一种方法,可以使用
    列表
    出列
    以及所有带有
    开始
    结束
    的东西,一次完成:)@xtoff:他提出的解决方案可以做到这一点@(否决这个答案的人):请评论一下你认为这个答案有什么错,这样我们可以学到一些东西,作者可以纠正他/她的答案。谢谢。看起来不错,很有效,非常接近我需要的。一句话:我尽量少用图书馆。那么
    boost::scoped_ptr
    真的有必要吗?
    scoped_ptr
    完全没有必要。只需按值存储迭代器即可。???我想我犯了一个愚蠢的错误,但是行
    typename-inner\u-it\u-type-m\u-inner\u-it
    ,则code>在'internal\u it\u type'之前给出编译器错误
    所需的嵌套名称说明符
    类型名
    (实际上是禁止的):
    。renmoving
    类型名
    会产生大量错误消息,第一个是:
    没有匹配的函数用于调用“展平迭代器::展平迭代器()”
    。另一种说法是,
    m_internal_it
    不是指针类型的MultiDim似乎有问题。我试过:向量tst;自动fw=多维::makeFlatView(tst);不幸的是,这无法用VC2017编译。@fhw72有趣。不幸的是,我已经很长时间没有在这个库上工作了,我再也没有Windows机器了。然而,如果你在我的回购协议中提出一个问题,我可以在我有时间的时候看看这件事。
    int main( int argc, char* argv[] )
    {   
        typedef std::vector<int> n1_t;
        typedef std::vector<std::deque<short> > n2_t;
        typedef std::list<std::vector<std::vector<std::vector<double> > > > n4_t;
        typedef std::vector<std::deque<std::vector<std::deque<std::vector<std::list<float> > > > > > n6_t;
        
        n1_t n1 = { 1, 2, 3, 4 };
        n2_t n2 = { {}, { 1, 2 }, {3}, {}, {4}, {}, {} };
        n4_t n4 = { { { {1.0}, {},  {}, {2.0}, {} }, { {}, {} }, { {3.0} } }, { { { 4.0 } } } };
        n6_t n6 = { { { { { {1.0f}, {},  {}, {2.0f}, {} }, { {}, {} }, { {3.0f} } }, { { { 4.0f } } } } } };
        
        flatten_iterator<n1_t, int> i1( n1 );
        while ( !i1.complete() )
        {
            std::cout << i1.current() << std::endl;
            i1.advance();
        }
        
        flatten_iterator<n2_t, short> i2( n2 );
        while ( !i2.complete() )
        {
            std::cout << i2.current() << std::endl;
            i2.advance();
        }
        
        flatten_iterator<n4_t, double> i4( n4 );
        while ( !i4.complete() )
        {
            std::cout << i4.current() << std::endl;
            i4.advance();
        }
        
        flatten_iterator<n6_t, float> i6( n6 );
        while ( !i6.complete() )
        {
            std::cout << i6.current() << std::endl;
            i6.advance();
        }
    }
    
    1
    2
    3
    4