title: STL-friendly pImpl class?
body: <p>I am maintaining a project that can take a considerable time to build so am trying to reduce dependencies where possible.  Some of the classes could make use if the <code>pImpl</code> idiom and I want to make sure I do this correctly and that the classes will play nicely with the STL (especially containers.)  Here is a sample of what I plan to do - does this look OK?  I am using <code>std::auto_ptr</code> for the implementation pointer - is this acceptable?  Would using a <code>boost::shared_ptr</code> be a better idea?</p>
  
  <p>Here is some code for a <code>SampleImpl</code> class that uses classes called <code>Foo</code> and <code>Bar</code>:</p>
  
  <pre><code>// SampleImpl.h
  #ifndef SAMPLEIMPL_H
  #define SAMPLEIMPL_H
  
  #include &lt;memory&gt;
  
  // Forward references
  class Foo;
  class Bar;
  
  class SampleImpl
  {
  public:
      // Default constructor
      SampleImpl();
      // Full constructor
      SampleImpl(const Foo&amp; foo, const Bar&amp; bar);
      // Copy constructor
      SampleImpl(const SampleImpl&amp; SampleImpl);
      // Required for std::auto_ptr?
      ~SampleImpl();
      // Assignment operator
      SampleImpl&amp; operator=(const SampleImpl&amp; rhs);
      // Equality operator
      bool operator==(const SampleImpl&amp; rhs) const;
      // Inequality operator
      bool operator!=(const SampleImpl&amp; rhs) const;
  
      // Accessors
      Foo foo() const;
      Bar bar() const;
  
  private:
      // Implementation forward reference
      struct Impl;
      // Implementation ptr
      std::auto_ptr&lt;Impl&gt; impl_;
  };
  
  #endif // SAMPLEIMPL_H
  
  // SampleImpl.cpp
  #include "SampleImpl.h"
  #include "Foo.h"
  #include "Bar.h"
  
  // Implementation definition
  struct SampleImpl::Impl
  {
      Foo foo_;
      Bar bar_;
  
      // Default constructor
      Impl()
      {
      }
  
      // Full constructor
      Impl(const Foo&amp; foo, const Bar&amp; bar) :
          foo_(foo),
          bar_(bar)
      {
      }
  };
  
  SampleImpl::SampleImpl() :
      impl_(new Impl)
  {
  }
  
  SampleImpl::SampleImpl(const Foo&amp; foo, const Bar&amp; bar) :
      impl_(new Impl(foo, bar))
  {
  }
  
  SampleImpl::SampleImpl(const SampleImpl&amp; sample) :
      impl_(new Impl(*sample.impl_))
  {
  }
  
  SampleImpl&amp; SampleImpl::operator=(const SampleImpl&amp; rhs)
  {
      if (this != &amp;rhs)
      {
          *impl_ = *rhs.impl_;
      }
      return *this;
  }
  
  bool SampleImpl::operator==(const SampleImpl&amp; rhs) const
  {
      return  impl_-&gt;foo_ == rhs.impl_-&gt;foo_ &amp;&amp;
          impl_-&gt;bar_ == rhs.impl_-&gt;bar_;
  }
  
  bool SampleImpl::operator!=(const SampleImpl&amp; rhs) const
  {
      return !(*this == rhs);
  }
  
  SampleImpl::~SampleImpl()
  {
  }
  
  Foo SampleImpl::foo() const
  {
      return impl_-&gt;foo_;
  }
  
  Bar SampleImpl::bar() const
  {
      return impl_-&gt;bar_;
  }
  </code></pre>