C++ template component architecture

A set of C++ templates for implementing a component architecture. This architecture allows developers to create easily extensible applications from components. A core engine defines a set of interfaces that components can implement to extend behaviour.

Several projects implement a similar architecture, including Eclipse and Trac.

Core -> Interface -> Component Implementation

Here is a completely contrived example, followed by the full template system below:

#include <iostream>
#include "ComponentArchitecture.h"

struct MyInterface : public Interface<MyInterface> {
  virtual void my_interface_method(int some_argument) = 0;
};

struct MyOtherInterface : public Interface<MyOtherInterface> {
  virtual void my_other_interface_method(int some_other_argument) = 0;
};

/* Class implementing the MyInterface and MyOtherInterface interfaces */
struct MyComponent : MyInterface, MyOtherInterface {
  void my_interface_method(int some_argument) {
    std::cout << "my_interface_method(" << some_argument << ")" << std::endl;
  }
  void my_other_interface_method(int some_other_argument) {
    std::cout << "my_other_interface_method(" << some_other_argument << ")" << std::endl;
  }
};

REGISTER_EXTENSION(MyComponent)

int main(int argc, char **argv) {
  /* Call my_interface_method() on all implementations of MyInterface */
  for (MyInterface::iterator i = MyInterface::begin(); i != MyInterface::end(); ++i)
    (*i)->my_interface_method(10);
  /* Call my_other_interface_method() on all implementations of MyOtherInterface */
  for (MyOtherInterface::iterator i = MyOtherInterface::begin(); i != MyOtherInterface::end(); ++i)
    (*i)->my_other_interface_method(10);
  return 0;
}

And here is the actual C++ implementation of the component architecture.

#ifndef COMPONENT_PATTERN_H__
#define COMPONENT_PATTERN_H__
#include <list>

/**
    Singleton template to ease construction of singleton classes. Use thus:

        class Foo : public Singleton<Foo> {
            private :
                friend class Singleton<Foo>;

                // Subclass constructor must be private to enforce singleton
                // semantics.
                Foo();
        };
*/

template <typename T>
class Singleton {
    public :
        /// Access the singleton object.
        static T &singleton() {
            if (!msingleton) msingleton = new T();
            return *msingleton;
        }

        /** Call on program termination. If shutdown() is not called, the
            singleton destructor will not be called. */
        static int shutdown(int rv = 0) {
            delete msingleton;
            msingleton = 0;
            return rv;
        }

    protected :
        Singleton() {}

    private :
        Singleton(const Singleton &);

        static T *msingleton;
};

template <typename T> T *Singleton<T>::msingleton;


/*
    Singleton class for accessing all of the implementations of a given
    Interface. It is easier to use the Interface<> iterator methods, but you
    can use these directly.
*/
template <typename T>
class ExtensionPoint : public Singleton<ExtensionPoint<T> > {
    public :
        typedef std::list<T*> Extensions;
        typedef typename Extensions::iterator iterator;
        typedef typename Extensions::const_iterator const_iterator;

        static void register_interface(T *interface) {
            Singleton<ExtensionPoint<T> >::singleton().mextensioninstances.push_back(interface);
        }

        static iterator begin() {
            return Singleton<ExtensionPoint<T> >::singleton().mextensioninstances.begin();
        }

        static iterator end() {
            return Singleton<ExtensionPoint<T> >::singleton().mextensioninstances.end();
        }

    private :
        friend class Singleton<ExtensionPoint>;

        ExtensionPoint() {}

        Extensions mextensioninstances;
};

/**
    Define a new interface. All interface methods should be pure virtual to
    force implementation in the extensions.

    eg.
        struct IHelpProvider : Interface<IHelpProvider> {
            virtual std::string get_help(std::string term) = 0;
        };

    To subsequently iterate over all objects implementing the IHelpProvider
    interface:

        for (IHelpProvider::iterator i = IHelpProvider::begin(); i != IHelpProvider::end(); ++i)
            cout << (*i)->get_help(term) << endl;
*/
template <typename T>
class Interface : public Singleton<T> {
    public :
        typedef std::list<T*> Extensions;
        typedef typename Extensions::iterator iterator;
        typedef typename Extensions::const_iterator const_iterator;

        static iterator begin() {
            return ExtensionPoint<T>::begin();
        }

        static iterator end() {
            return ExtensionPoint<T>::end();
        }
    protected :
        virtual ~Interface() {}

        Interface() {
            ExtensionPoint<T>::register_interface(static_cast<T*>(this));
        }
};

template <typename T>
struct RegisterExtension {
    RegisterExtension() {
        Singleton<T>::singleton();
    }
};

/**
    Helper macro to instantiate an extension object. Probably not necessary,
    but makes it easier to find extensions in source.

    eg.

    Without singleton protection, simply:

        struct ManHelp : IHelpProvider {
            std::string get_help(std::string term) {
                if (term.substr(0, 4) == "man:")
                    ....
            }
        };

    Or as a singleton:

        struct ManHelp : Singleton<ManHelp>, IHelpProvider {
            std::string get_help(std::string term) {
                if (term.substr(0, 4) == "man:")
                    ....
            }

            // Prevent accidental instantation
            private :
                friend class Singleton<ManHelp>;
                ManHelp() {}
        };

    Then finally:

        REGISTER_EXTENSION(ManHelp)
*/

#define REGISTER_EXTENSION(extension) \
    static RegisterExtension<extension> __##extension##_extension__;

#endif