On Mon, 2007-03-05 at 19:46 +0000, Gordon Sim wrote:
> Alan Conway wrote:
> > #A _ BDBStore working with 0-9 trunk.
> 
> I'll take this one as I will be doing some work on the BdbStore to 
> finish off distributed transactions anyway.
> 
> > #B _ Pimpl API for broker/messagestore
> 
> I'll have a go at this as well along with the general cleanup of the 
> message store api and then request further comments from you both.

Excellent.

Attached is a sketch of the Pimpl idiom using shared_ptr, including the
inheritance case. Does it look sensible? Can we make it simpler with
templates (I can't figure out how.) Once we're agreed we can go ahead
with the API cleanup.

Cheers,
Alan.
#include <iostream>

#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/current_function.hpp>
using namespace std;


// ==== Foo.h
/** Example Pimpl class
 * NB: No inline or virtual functions! 
 */
class Foo {
  public:
    // Use default copy and assign. No other public ctors.
    // Get instances from factory objects or static factory functions:
    static Foo create();
    // Forwarding functions:
    void foo();

  protected: // Or private if no classes derive from this.
    class Impl;
    Foo(Impl* i) : impl(i) {}   // For static factory
    boost::shared_ptr<Impl> impl;
};

// ==== Foo.cpp
// Implementation - use virtual as normal.
class Foo::Impl {
  public:
    Impl() { cout << BOOST_CURRENT_FUNCTION << endl; }
    virtual ~Impl() { cout << BOOST_CURRENT_FUNCTION << endl; }
    virtual void foo() { cout << BOOST_CURRENT_FUNCTION << endl; }
};

// Pimpl functions
Foo Foo::create() { return Foo(new Foo::Impl()); }
void Foo::foo() { impl->foo(); }

// ==== SpecialFoo.h

/** Example derived class
 * Note do not need to repeat inherited virtual functions regardless of whether
 * they will be overridden by the derived implementation.
 */
class SpecialFoo : public Foo {
  public:
    static SpecialFoo create(); // Factory
    void special();

  private:
    class Impl;
    // SpecialFoo::Impl inherits Foo::Impl so this is OK.
    SpecialFoo(Impl* i);
    Impl* ptr() const;
};

// ==== SpecialFoo.cpp
// Implementation, inherits Foo::Impl
/** Derived implementation
 * Use virtual as normal in implementations.
 */
class SpecialFoo::Impl : public Foo::Impl {
  public:
    Impl() { cout << BOOST_CURRENT_FUNCTION << endl; }
    virtual ~Impl() { cout << BOOST_CURRENT_FUNCTION << endl; }
    virtual void foo() { cout << BOOST_CURRENT_FUNCTION << endl; }
    virtual void special() { cout << BOOST_CURRENT_FUNCTION << endl; }
};

// Pimpl functions
SpecialFoo::SpecialFoo(SpecialFoo::Impl* i) : Foo(i) {} 
SpecialFoo::Impl* SpecialFoo::ptr() const {
    return dynamic_cast<SpecialFoo::Impl*>(impl.get());
}
SpecialFoo SpecialFoo::create() { return SpecialFoo(new Impl()); }
void SpecialFoo::special() { ptr()->special(); }








int main(int, char**) {
    Foo foo = Foo::create();
    foo.foo();
    {
        Foo f = foo;
        f.foo();
    }
    SpecialFoo s = SpecialFoo::create();
    s.foo();
    s.special();
}

Reply via email to