Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
319 views
in Technique[技术] by (71.8m points)

c++ - Using Iterators to hide internal container and achieve generic operation over a base container

I basically want to have a base container class which can return a generic iterator that can be used to traverse an instance of the container class, without needing to specify iterator templates. I think I cannot implement the base container over a class template, which would then require a traversal algorithm based on template classes which are not known in advance. The base container can be inherited and implemented using any (custom or standard) container type/implementation within. Here are some code samples to make it clear:

struct MyObject {
  int myInt;
}

// an abstract container
class BaseContainer {
public:
  virtual void insertMyObject(MyObject& obj) = 0;
  virtual iterator getFirst(); // the iterator type is for demonstration purposes only
  virtual iterator getLast();  // the iterator type is for demonstration purposes only
}

// Sample container class that uses a std::vector instance to manage objects
class BaseContainer_Vector : public BaseContainer {
public:
  void insertMyObject(MyObject& obj); // e.g. just pushes back to the vector
  iterator getFirst(); // needs to override the iterator?
  iterator getLast();  // needs to override the iterator?
private:
  std::vector<MyObject> objectContainer;
}

I will then have a list of container objects, and I want to iterate over both these containers and the objects stored.

std::vector<MyContainer*> containers;
for(int i=0 ; i<containers.size() ; i++){
  iterator i    = containers[i]->getFirst();
  iterator iend = containers[i]->getLast();
  for(; i != iend ; i++) {
    std::cout << (*i).myInt << std::endl;
  }
}

I further would like to have support for boost foreach macro statement. It supports extensions as long as range_begin and range_end functions are properly. But, the example in boost doc uses std::string::iterator as return type, while what I need is a generic iterator class and I could not yet figure out how to do that as well.

std::vector<MyContainer*> containers;
for(int i=0 ; i<containers.size() ; i++){
  BOOST_FOREACH(MyObject obj, *(containers[i])) {
    std::cout << obj.myInt << std::endl;
  }
}

I think I can define my own iterator class, then each class that extends BaseContainer should define their own iterator extending that basic iterator. Yet, I would prefer to use standard iterators (stl or boost) to support this structure, rather that writing my own iterators. I guess this approach will work, but I am open to comments regarding its efficiency.

Is there a feasible approach that can solve this problem elegantly? Or am I missing a simple point which can solve this problem without any pain?

A similar question can be found here, but the proposed solutions seem a bit complex for my needs, and the requirements differ as far as I can understand.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's gonna be complicated.

As already stated, first you need your iterators to have value semantic because since they are usually copied around otherwise it would result in object slicing.

class BaseContainer
{
protected:
  class BaseIteratorImpl; // Abstract class, for the interface

public:
  class iterator
  {
  public:
    iterator(const BaseIteratorImpl& impl);
  private:
    BaseIteratorImpl* m_impl;
  };

  iterator begin();
  iterator end();
}; // BaseContainer

Then, BaseIterator forwards all methods to m_impl.

This way you achieve value semantic syntax with a polymorphic core.

Obviously, you'll have to handle deep-copy semantics and proper destruction.

Some notes:

  • publish both an iterator and a const_iterator class
  • name your methods empty, size, begin, end etc... for compatibility with STL algorithms

You can check SGI Iterators for help about the Concepts and operations your operators should support for maximum compatibility.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...