C++ – Allow Iteration of Internal Vector Without Leaking Implementation

c

I have a class that represents a list of people.

class AddressBook
{
public:
  AddressBook();

private:
  std::vector<People> people;
}

I want to allow clients to iterate over the vector of people. The first thought I had was simply:

std::vector<People> & getPeople { return people; }

However, I do not want to leak the implementation details to the client. I may want to maintain certain invariants when the vector is modified, and I lose control over these invariants when I leak the implementation.

What's the best way to allow iteration without leaking the internals?

Best Answer

allow iteration without leaking the internals is exactly what the iterator pattern promises. Of course that is mainly theory so here is a practical example:

class AddressBook
{
  using peoples_t = std::vector<People>;
public:
  using iterator = peoples_t::iterator;
  using const_iterator = peoples_t::const_iterator;

  AddressBook();

  iterator begin() { return people.begin(); }
  iterator end() { return people.end(); }
  const_iterator begin() const { return people.begin(); }
  const_iterator end() const { return people.end(); }
  const_iterator cbegin() const { return people.cbegin(); }
  const_iterator cend() const { return people.cend(); }

private:
  peoples_t people;
};

You provide standard begin and end methods, just like sequences in the STL and implement them simply by forwarding to vector's method. This does leak some implementation detail namely that you're returning a vector iterator but no sane client should ever depend on that so it is imo not a concern. I've shown all overloads here but of course you can start by just providing the const version if clients should not be able to change any People entries. Using the standard naming has benefits: anyone reading the code immediately knows it provides 'standard' iteration and as such works with all common algorithms, range based for loops etc.