Differentiating pimpl idiom classes in c++

Discussion in 'C++' started by Graham Reitz, Apr 16, 2008.

  1. Graham Reitz

    Graham Reitz Guest

    What are good strategies for selecting, either at run-time or compile
    time, various pimpl'ed implementations? While retaining the ability
    to switch implementations without recompiling.

    Boost has an example but with only one implementation class: (what
    would an example with 2 implementation classes look like?)

    http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/sp_techniques.html#pimpl

    The pimpl'ed class cpp file has to include at least one implementation
    header file. Is there a method to avoid changing that included header
    when switching implementations?

    Or, are we using the pimpl idiom incorrectly?

    thanks,
    graham
    Graham Reitz, Apr 16, 2008
    #1
    1. Advertising

  2. Graham Reitz

    Noah Roberts Guest

    Graham Reitz wrote:
    > What are good strategies for selecting, either at run-time or compile
    > time, various pimpl'ed implementations? While retaining the ability
    > to switch implementations without recompiling.
    >
    > Boost has an example but with only one implementation class: (what
    > would an example with 2 implementation classes look like?)
    >
    > http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/sp_techniques.html#pimpl
    >
    > The pimpl'ed class cpp file has to include at least one implementation
    > header file. Is there a method to avoid changing that included header
    > when switching implementations?
    >
    > Or, are we using the pimpl idiom incorrectly?


    You need to abstract your pimpl and make a factory. You'll always need
    to recompile if you add a new pimpl type, but you can switch between
    them. It will no longer be a pimpl at this point.

    It sounds like what you really want is a State. Look up that pattern.
    Noah Roberts, Apr 16, 2008
    #2
    1. Advertising

  3. Graham Reitz

    Brian Szmyd Guest

    On 4/16/2008 9:00:17 AM, Graham Reitz wrote:
    > What are good strategies for selecting, either at run-time or compile
    > time, various pimpl'ed implementations? While retaining the ability
    > to switch implementations without recompiling.
    >
    > Boost has an example but with only one implementation class: (what
    > would an example with 2 implementation classes look like?)
    >
    > http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/sp_techniques.html#pimpl
    >
    > The pimpl'ed class cpp file has to include at least one implementation
    > header file. Is there a method to avoid changing that included header
    > when switching implementations?
    >
    > Or, are we using the pimpl idiom incorrectly?
    >
    > thanks,
    > graham
    >


    Funny you asked, as I just finished doing exactly this for a project I'm
    working on. Here's what I did:

    // Factory.h
    #include <map>
    #include <string>
    template <typename T>
    class Factory
    {
    public:
    typedef std::map<std::string, typename T::constructor_type> Map;

    static Factory<T>* getFactory()
    {
    if ( ! m_instance )
    m_instance = new Factory<T>;
    return m_instance;
    }

    typename T::constructor_type createKind( std::string output_kind )
    {
    typename Map::iterator it;
    if if ( ( it = constructorMap.find( output_kind ) ) != constructorMap.end() )
    return (*it).second;
    // Throw something here
    }

    void void registerKind( std::string kind, typename T::constructor_type
    constructor) {
    constructorMap[kind] = constructor;
    }

    private:
    Map constructorMap;
    static Factory<T>* m_instance;
    };

    // FooImpl.h
    #include <boost/function.hpp>
    #include <boost/shared_ptr.hpp>
    #include "Factory.h"
    FooImpl
    {
    public:
    typedef typedef boost::function<boost::shared_ptr<FooImpl>()>
    constructor_type; static Factory<FooImpl> factory;
    };

    // FooImpl.cpp
    Factory<FooImpl> FooImpl::factory;

    // FooFake.cpp
    #include "FooImpl.h"
    class FooFake :
    public FooImpl
    {
    private:
    struct FooFakeCreator
    {
    FooFakeCreator oFakeCreator () {
    FooImpl::factory.getFactory()->registerKind("Fake", FooFakeCreator::create );
    static static boost::shared_ptr<FooImpl> create () { return
    boost::shared_ptr<FooImpl>( new FooFake() ); } }
    static FooFakeCreator m_creator;
    };

    FooFake::FooFakeCreator FooFake::m_creator;


    You could probably clean this up, but it allows your users to be agnostic to
    the different implementations. I didn't include the actual Foo object, that
    in my case contains a weak pointer to a FooImpl. My implementation also
    requires the caller to FooImpl::factory->createKind(string) to provide the
    type, but this could be read in from a config file and you could remove this
    requirement. Have some sort of factory registry that createKind would look
    into.

    This may or may not have a "pattern name", let me know someone if it does.
    Brian Szmyd, Apr 17, 2008
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Icosahedron

    Pimpl Idiom

    Icosahedron, Nov 20, 2003, in forum: C++
    Replies:
    7
    Views:
    685
    Icosahedron
    Nov 22, 2003
  2. Debajit  Adhikary
    Replies:
    2
    Views:
    2,019
    Christopher Benson-Manica
    Jul 15, 2004
  3. Peteris Krumins
    Replies:
    2
    Views:
    465
    Peteris Krumins
    Aug 31, 2005
  4. jimmy

    friendship and pImpl idiom

    jimmy, Feb 8, 2006, in forum: C++
    Replies:
    3
    Views:
    430
    Alf P. Steinbach
    Feb 9, 2006
  5. Noah Roberts

    pimpl idiom and singletons

    Noah Roberts, May 24, 2007, in forum: C++
    Replies:
    4
    Views:
    428
    Noah Roberts
    May 25, 2007
Loading...

Share This Page