What is the cleanest implementation of this container of typed containers?

I have different types of, say A, B, Cthat all derive from a base class Base:

class Base { ... };
class A : public Base { ... };
class B : public Base { ... };
class C : public Base { ... };

I need a container, call it Master, which contains pointers to type objects A, Band C. I want the container to Masterprovide an iterator over all contained objects Base, as well as specifically typed iterators on top of all contained objects A, Band C. I use as storage std::vector, but it would be nice if it were easy to switch later.

Conceptually, this is an interface that Mastershould be presented in the outside world:

class Master {

  public:

    add(A *a);
    add(B *b);
    add(C *c);

    remove(Base *base);

    iterator<A*> a_begin();
    iterator<A*> a_end();
    iterator<B*> b_begin();
    iterator<B*> b_end();
    iterator<C*> c_begin();
    iterator<C*> c_end();
    iterator<Base*> base_begin();
    iterator<Base*> base_end();
    // also: reverse iterators, const iterators, reverse const iterators
};

. , someMaster.begin<A>() .

, , . . , Master , D, E F ( Base). , .

dynamic_cast ing, . , . ?

+3
4

, :

// Beware, brain-compiled code ahead
template< typename T >
class typed_container
{
  typedef std::vector<T> data_t;
public:
  typedef data_t::iterator iterator;
  iterator begin() {return data_.begin();}
  iterator end  () {return data_.end();}
private:
  data_t data_;
};

typedef my_type_list<A,B,C> types_t;

class master : public derive_from< typed_container, types_t > {
  template< typename T >
  struct traits {
    typedef typename typed_container<T>::iterator iterator;
    iterator begin(typed_container<T>& c) {return c.begin();}
    iterator end  (typed_container<T>& c) {return c.end  ();}
  };
public:
  template< typename T > 
  typename traits<T>::iterator begin() {return traits<T>::begin(*this);}
  template< typename T > 
  typename traits<T>::iterator end  () {return traits<T>::end  (*this);}

  typedef my_assembling_iterator<types_t> iterator;

  iterator begin() {return my_assembling_iterator<types_t>.begin(*this);}
  iterator end  () {return my_assembling_iterator<types_t>.end  (*this);}
};

my_type_list ( ), derive_from ( , ), my_assembling_iterator ( - ),


++ 03 . ( ),

typedef my_type_list<A,B,C>::result_t types_t

, , ( ).

derive_from :

//Beware, brain-compiled code ahead!
template< template<typename> class C, class  >
struct derive_from;

template< template<typename> class C >
struct derive_from< C, nil > {};

template< template<typename> class C, typename Head, typename Tail >
struct derive_from< C, my_type_list<Head,Tail> > : public C<Head>
                                                 , public derive_from<C,Tail> {};

. ? () ? - ?

+4

-, Boost.Variant.
.
boost::get<T>(), T.
T, .
, , , A, B C , , Base, usecases .

+4

RTTI + boost filter_iterator? , , RTTI, filter_iterator , _, .

+2

:

"" ?

- , (a_begin/a_end vs. b_begin/b_end vs. c_begin/c_end). - Java , end master .

:

master *m = ..;
master::iterator<A*> a = m->getA():
while ( a->hasNext() ) {
    A *current = a->next();
    current->doSomething()
}

, (A, B, C).

, - -, get() m->get<A>(). , (. ), .

How to make iterators efficient?

An iterator Baseshould iterate over all contained objects, specific iterators should only iterate over subsets of contained objects. Do this, I propose to make masterseveral objects std::vector, one for a specific type.

An iterator Acan then iterate over a vector containing everything A*, the same for other specific types. The iterator Basesimply went through all the containers, treating them as one continuous container.

0
source

Source: https://habr.com/ru/post/1753129/


All Articles