创建一个遍历2个容器的c ++迭代器 [英] Make a c++ iterator that traverses 2 containers

查看:152
本文介绍了创建一个遍历2个容器的c ++迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个像下面这样的容器。它有2个子容器,称为A和B,我需要能够遍历只是A,只是B,A和B组合。我不想为冗余数据使用额外的空间,所以我想使我自己的迭代器迭代A和B组合。什么是最简单的方法来使自己的迭代器?

最终,我认为这不是好的设计。我重新设计了整个类。 +1重构。然而,我没有充分解决这个问题。这里是我做了什么的缩写版本,供参考;它使用boost :: filter_iterator。让T是容器中的类型。

 枚举标志
{
A_flag,
B_flag
};

class T_proxy
{
public:
T_proxy(const T& t,Flag f):t_(t),flag_(f){}
操作符T()const {return t_;}
标志flag()const {return flag_;}
类比较
{
public:
比较):matchFlag_(f){}
operator()(const T_proxy& tp){return tp.flag()== matchFlag_;}
private:
Flag matchFlag_;
};
private:
T t_;
Flag flag_;
};

class AB_list
{
public:
typedef T_proxy :: Compare Compare;
typedef vector< T_proxy> :: iterator iterator;
typedef boost :: filter_iterator< Compare,iterator> sub_iterator;
void insert(const T& val,flag f){data_.insert(T_proxy(val,f));}
//其他方法...

整个序列
迭代器begin(){return data_.begin();}
iterator end(){return data_.end();}

//只是A
sub_iterator begin_A(){return sub_iterator(Compare(A_flag),begin(),end());
sub_iterator end_A(){return sub_iterator(Compare(A_flag),end(),end());

//只是B基本上是一样的
private:
vector< T_proxy>数据_;
};


//用法
AB_list mylist;
mylist.insert(T(),A_flag);
for(AB_list :: sub_iterator it = mylist.begin_A(); it!= mylist.end_A(); ++ it)
{
T temp = * it; // T_proxy可以转换为T
cout<<温度
}


解决方案

一个类似的问题。



使用像 Boost.MultiIndex 来做你想要的。它缩放很好,如果你想添加新的索引,有很少的锅炉板代码。它通常也更多空间和时间效率

  typedef multi_index_container< 
container,
indexed_by<
sequenced<> ;, //给你一个列表,如interface
ordered_unique< Container,std :: string,& Container :: a_value> ;, //给你一个名字map $ b ordered_unique< Container,std :: string,& Container :: b_value> //给你一个名字的查找,如map
>
>容器;

如果迭代一个索引,可以使用迭代器投影概念切换到另一个索引图书馆。


I have a need for a "container" that acts like the following. It has 2 subcontainers, called A and B, and I need to be able to iterate over just A, just B, and A and B combined. I don't want to use extra space for redundant data, so I thought of making my own iterator to iterate over A and B combined. What is the easiest way to make your own iterator? Or, what is another way to do this?

EDIT Ultimately, I don't think it was good design. I have redesigned the entire class heirarchy. +1 for refactoring. However, I did solve this problem sufficiently. Here's an abbreviated version of what I did, for reference; it uses boost::filter_iterator. Let T be the type in the container.

enum Flag
{
    A_flag,
    B_flag
};

class T_proxy
{
public:
    T_proxy(const T& t, Flag f) : t_(t), flag_(f) {}
    operator T() const {return t_;}
    Flag flag() const {return flag_;}
    class Compare
    {
    public:
        Compare(Flag f) : matchFlag_(f) {}
        operator() (const T_proxy& tp) {return tp.flag() == matchFlag_;}
    private:
        Flag matchFlag_;
    };
private:
    T t_;
    Flag flag_;
};

class AB_list
{
public:
    typedef T_proxy::Compare Compare;
    typedef vector<T_proxy>::iterator iterator;
    typedef boost::filter_iterator<Compare, iterator> sub_iterator;
    void insert(const T& val, Flag f) {data_.insert(T_proxy(val, f));}
    // other methods...

    // whole sequence
    iterator begin() {return data_.begin();}
    iterator end() {return data_.end();}

    // just A
    sub_iterator begin_A() {return sub_iterator(Compare(A_flag), begin(), end());
    sub_iterator end_A() {return sub_iterator(Compare(A_flag), end(), end());

    // just B is basically the same
private:
    vector<T_proxy> data_;
};


// usage
AB_list mylist;
mylist.insert(T(), A_flag);
for (AB_list::sub_iterator it = mylist.begin_A(); it != mylist.end_A(); ++it)
{
    T temp = *it; // T_proxy is convertible to T
    cout << temp;
}

解决方案

I will repost my answer to a similar question. I think this will do what you want.

Use a library like Boost.MultiIndex to do what you want. It scales well and there is a lot less boiler plate code if you want to add new indexes. It is also usually more space and time efficient

typedef multi_index_container<
  Container,
  indexed_by<
    sequenced<>, //gives you a list like interface
    ordered_unique<Container, std::string, &Container::a_value>, //gives you a lookup by name like map
    ordered_unique<Container, std::string, &Container::b_value> //gives you a lookup by name like map
  >
> container;

If you are iterating over one index, you can switch to another index by using the iterator projection concept in the library.

这篇关于创建一个遍历2个容器的c ++迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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