0

I have a C++ pure virtual base class/ interface with several implementations which are defined in different places in the code, and other implementations may be added later. I need a way to register the available implementations, read in (from a configuration file, user input, etc) which implementation of the interface to use, and then construct an instance of that implementation.

How can I do this in a general way (ie, table driven, not with a switch/ case statement that lists each one of implementations explicitly)? I'm having trouble figuring how to go from a runtime value indicating the type to a compile time type that I can instantiate.

Does boost have anything like this?

Ken
  • 619
  • 1
  • 7
  • 11
  • "and other implementations may be added later." Added at runtime? – bames53 Nov 01 '12 at 15:41
  • no, added at compile time. but, say this is a library. i want users of the library to be able to add implementations of an interface without needing to modify the library code, as would be required if every implementation were listed in a switch statement in the library. – Ken Nov 01 '12 at 16:23

1 Answers1

1

The standard approach involves a creational pattern called factory, which instantiates a concrete type based on a user-supplied identifier.

If you're using Boost already, have a look at Boost.Functional/Factory, but it's not very difficult to build a table-based dispatching mechanism yourself. This is how you use the Boost version with run-time polymorphism:

struct abstract
{
    virtual ~abstract() = default;
    virtual void f() = 0;
};

struct concrete1 : abstract
{
    virutal void f() override;
};

struct concrete2 : abstract
{
    virutal void f() override;
};

typedef boost::function<abstract*()>  abstract_factory;

int main()
{
    // Here, each factory refers to a function, although sometimes
    // people use the term factory to mean the dispatch table itself.
    std::map<std::string, abstract_factory> factories;
    factories["foo"] = boost::factory<concrete1*>();
    factories["bar"] = boost::factory<concrete2*>();

    // Create a new concrete object.
    auto foo = factories["foo"]();

    // vtable dispatch "concrete1".
    foo->f();

    ...
} 
Community
  • 1
  • 1
mavam
  • 12,242
  • 10
  • 53
  • 87