views:

107

answers:

4

Hi there.

Actually, I have a design question here. Its very simple but the point is:

I have one C++ class that has a STL vector declared as a private member. But the clients of that class need to iterate over this vector.

In C# we have a very handy statement, the Yield, that in cases like that, you write a function returning an IEnumerable and it "yields" you a nice way to iterate over a private container inside that class.

I'm just trying to find an elegant solution for C++, instead of using methods like GetValue(int idx).

Any suggestions?

Example:

class Fat
{
   public:
      Fat();
   // some code here ...

   private:
      void LoadSectors(SECT startPoint);
      std::vector<SECT>sectors;

};

class Storage
{
   public:
      Storage(string CompoundFile);

      //For example, this method will receive a ref to my fat system and iterate over
      //the fat array in order to read every sector. 
      LoadStrem(Fat& fat);

};

This is far simple example.

+4  A: 

You can either create an accessor function which returns a reference (or preferably const reference) to the vector, or you can create begin() and end() accessor functions which return the appropriate vector iterators.

Charles Salvia
+6  A: 

There's no syntactic sugar in C++ analogous to yield in C#. If you want to create a class, instances of which should be iterable in the same way stock STL collections are, then you have to implement an iterator for your class, expose it as ::iterator on your type, and provide begin() and end() member functions.

Pavel Minaev
The vector already implements an iterator. You can just do `typedef vector<SECT>::const_iterator const_iterator;` and (perhaps) `typedef vector<SECT>::iterator iterator;`
UncleBens
+2  A: 

It always hurts when you need to publish the innards of your class...

You may be able to solve it by providing algorithms as the stl does: provide a foreach function on the object's interface.

class S { 
   std::vector<int> v;

public:
   //... and some methods to populate the vector

   template< typename F > F& foreach( F& f ) { 
      return std::for_each( v.begin(), v.end(), f );
   }

};

This way, the class remains 'closed', but you have the flexibility you need. You can also add a copy function, and maybe a transform; these are the ones I most frequently need.

xtofl
There may be similar reasons to publish the "innards" as `std::vector` publishes its "innards" - that is, it could be essentially a container class just happening to use a `std::vector` as the underlying type. P.S Exposing the contents of the vector won't expose the vector itself.
UncleBens
Er, this isn't what the STL does. Quite the contrary. What the STL *doesn't* do is couple the container and the iteration algorithm.
jalf
@jalf: you're right: that would mean `vector.foreach( ... )`. I meant providing _algorithms_ as the stl does.
xtofl
+1  A: 

Let your class expose iterators.

class Fat
{
   public:
    typedef std::vector<SECT>::iterator iterator;

    iterator begin() { return sectors.begin(); }
    iterator end() { return sectors.end(); }

      Fat();
   // some code here ...

   private:
      void LoadSectors(SECT startPoint);
      std::vector<SECT>sectors;

Then the surrounding code can traverse the elements of the vector freely, through just a pair of iterators.

jalf