0

I've got a container class that has its implementation hidden through the Pimpl idiom.

The problem is: how to expose a typedef defined within the implementation class onto the public class? Also, I want to make sure that the implementation details are not exposed within the typedef (we should not see it's a vector).

The code below complains during compilation saying that MyContainer::Impl is an incomplete type. I just can't seem to find any workaround.

I've stumbled upon a similar question on How can I expose iterators without exposing the container used? pointing to an article about type erasures, but I'm not sure if I can apply all this reading to what I need?

I'm using C++11.

class MyContainer
{
private:
  class Impl;
  std::unique_ptr<Impl> m_d;

public:
  typedef Impl::Iterator Iterator;
  //typedef std::vector<int>::iterator Iterator; //< No!

  MyContainer() = default;
  ~MyContainer() = default;
  Iterator begin();
};


class MyContainer::Impl
{
public:
  typedef std::vector<int>::iterator Iterator;

  Impl() = default;
  ~Impl() = default;

  std::vector<int> items;
};


MyContainer::Iterator MyContainer::begin()
{
  return m_d->items.begin();
}
Community
  • 1
  • 1
ChristopherC
  • 1,635
  • 16
  • 31
  • Wouldn't that partially defeat the purpose of hiding the implementation? – juanchopanza Apr 26 '14 at 18:42
  • I wouldn't think so? It's obvious from the header file that `MyContainer` points to an `MyContainer::Impl` implementation anyways, so I'm not sure where would be the harm into forwarding a typedef from there? I'm open to suggestions anyhow. – ChristopherC Apr 26 '14 at 18:47
  • If the typedef depends on the implementation, then you are leaking details. If it doesn't, then you could swap the pointer to an incomplete type for a pointer to a complete abstract class. That abstract class could could define the typedef. – juanchopanza Apr 26 '14 at 18:51
  • 1
    Expose your own random access iterator into a contiguous buffer, or expose raw pointers as iterators, or (inefficient) expose a type-erased iterator. For efficient use the client code needs to know lots about the type when they are using values of the type. Type erasure (another pimpl level, but in the iterator) would let you hide details from client if you need to. – Yakk - Adam Nevraumont Apr 26 '14 at 19:26
  • Even if you do find a way to expose this typedef, how are you going to use it outside the class? It will still be an incomplete type for any "user" code, unless you include your implementation details from there. So, I don't think there's really any point in hiding the iterator class: it's part of your public interface anyway. Unless, of course, you want to allocate iterators dynamically and use them as opaque objects with some special manipulation methods in the owner class -- but that doesn't seem like a good idea to me. – Kirinyale Apr 26 '14 at 19:48

0 Answers0