#include <string>
#include <map>
#include <iostream>
 
class Whatever {
public:
    // контракт
    virtual void foo() = 0;
};
 
class WhateverFactory {
public:
    typedef Whatever* (*WhateverCtor)();
 
    static void registerClass(const std::string &name, WhateverCtor ctor) {
        if ( m_plugins.find(name) == m_plugins.end() ) {
            m_plugins[name] = ctor;
        }
    }
 
    static bool isRegistered(const std::string &cls) {
        return m_plugins.find(cls) != m_plugins.end();
    }
 
    static Whatever* createInstanceOf(const std::string &name) {
        std::map<std::string, WhateverCtor>::iterator ctor;
        if ( (ctor = m_plugins.find(name)) != m_plugins.end() ) {
            return ctor->second();
        } else {
            return NULL;
        }
    }
 
private:
    WhateverFactory() {}
 
    static std::map<std::string, WhateverCtor> m_plugins;
};
 
std::map<std::string, WhateverFactory::WhateverCtor> WhateverFactory::m_plugins;
 
class HelloWorld : public Whatever {
public:
    HelloWorld() : m_message("Hello, World!") {}
 
    void foo() {
        std::cout << m_message << std::endl;
    }
 
    static HelloWorld* create() {
        return new HelloWorld;
    }
 
private:
    std::string m_message;
};
 
void load() {
    WhateverFactory::registerClass("HelloWorld", reinterpret_cast<WhateverFactory::WhateverCtor>(HelloWorld::create));
}
 
int main() {
    load();
    Whatever *w = WhateverFactory::createInstanceOf("HelloWorld");
    if ( w ) {
        w->foo();
    }
 
    return 0;
}
				I2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPG1hcD4KI2luY2x1ZGUgPGlvc3RyZWFtPgoKY2xhc3MgV2hhdGV2ZXIgewpwdWJsaWM6CiAgICAvLyDQutC+0L3RgtGA0LDQutGCCiAgICB2aXJ0dWFsIHZvaWQgZm9vKCkgPSAwOwp9OwoKY2xhc3MgV2hhdGV2ZXJGYWN0b3J5IHsKcHVibGljOgogICAgdHlwZWRlZiBXaGF0ZXZlciogKCpXaGF0ZXZlckN0b3IpKCk7CgogICAgc3RhdGljIHZvaWQgcmVnaXN0ZXJDbGFzcyhjb25zdCBzdGQ6OnN0cmluZyAmbmFtZSwgV2hhdGV2ZXJDdG9yIGN0b3IpIHsKICAgICAgICBpZiAoIG1fcGx1Z2lucy5maW5kKG5hbWUpID09IG1fcGx1Z2lucy5lbmQoKSApIHsKICAgICAgICAgICAgbV9wbHVnaW5zW25hbWVdID0gY3RvcjsKICAgICAgICB9CiAgICB9CgogICAgc3RhdGljIGJvb2wgaXNSZWdpc3RlcmVkKGNvbnN0IHN0ZDo6c3RyaW5nICZjbHMpIHsKICAgICAgICByZXR1cm4gbV9wbHVnaW5zLmZpbmQoY2xzKSAhPSBtX3BsdWdpbnMuZW5kKCk7CiAgICB9CgogICAgc3RhdGljIFdoYXRldmVyKiBjcmVhdGVJbnN0YW5jZU9mKGNvbnN0IHN0ZDo6c3RyaW5nICZuYW1lKSB7CiAgICAgICAgc3RkOjptYXA8c3RkOjpzdHJpbmcsIFdoYXRldmVyQ3Rvcj46Oml0ZXJhdG9yIGN0b3I7CiAgICAgICAgaWYgKCAoY3RvciA9IG1fcGx1Z2lucy5maW5kKG5hbWUpKSAhPSBtX3BsdWdpbnMuZW5kKCkgKSB7CiAgICAgICAgICAgIHJldHVybiBjdG9yLT5zZWNvbmQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gTlVMTDsKICAgICAgICB9CiAgICB9Cgpwcml2YXRlOgogICAgV2hhdGV2ZXJGYWN0b3J5KCkge30KCiAgICBzdGF0aWMgc3RkOjptYXA8c3RkOjpzdHJpbmcsIFdoYXRldmVyQ3Rvcj4gbV9wbHVnaW5zOwp9OwoKc3RkOjptYXA8c3RkOjpzdHJpbmcsIFdoYXRldmVyRmFjdG9yeTo6V2hhdGV2ZXJDdG9yPiBXaGF0ZXZlckZhY3Rvcnk6Om1fcGx1Z2luczsKCmNsYXNzIEhlbGxvV29ybGQgOiBwdWJsaWMgV2hhdGV2ZXIgewpwdWJsaWM6CiAgICBIZWxsb1dvcmxkKCkgOiBtX21lc3NhZ2UoIkhlbGxvLCBXb3JsZCEiKSB7fQoKICAgIHZvaWQgZm9vKCkgewogICAgICAgIHN0ZDo6Y291dCA8PCBtX21lc3NhZ2UgPDwgc3RkOjplbmRsOwogICAgfQoKICAgIHN0YXRpYyBIZWxsb1dvcmxkKiBjcmVhdGUoKSB7CiAgICAgICAgcmV0dXJuIG5ldyBIZWxsb1dvcmxkOwogICAgfQoKcHJpdmF0ZToKICAgIHN0ZDo6c3RyaW5nIG1fbWVzc2FnZTsKfTsKCnZvaWQgbG9hZCgpIHsKICAgIFdoYXRldmVyRmFjdG9yeTo6cmVnaXN0ZXJDbGFzcygiSGVsbG9Xb3JsZCIsIHJlaW50ZXJwcmV0X2Nhc3Q8V2hhdGV2ZXJGYWN0b3J5OjpXaGF0ZXZlckN0b3I+KEhlbGxvV29ybGQ6OmNyZWF0ZSkpOwp9CgppbnQgbWFpbigpIHsKICAgIGxvYWQoKTsKICAgIFdoYXRldmVyICp3ID0gV2hhdGV2ZXJGYWN0b3J5OjpjcmVhdGVJbnN0YW5jZU9mKCJIZWxsb1dvcmxkIik7CiAgICBpZiAoIHcgKSB7CiAgICAgICAgdy0+Zm9vKCk7CiAgICB9CgogICAgcmV0dXJuIDA7Cn0=