I don't know why your aversion to writing the create() function. So here is what I implemented.
#include <iostream>
NOTE. I did not do everything you have, I just implemented the create function. I will leave the final implementation to you.
This uses perfect forwarding to allow the varidict template to pass any number of parameters to the constructor. The registration function may then store a pointer to a function for a particular instance of the template for a specific set of parameters.
EDIT
I forgot to use the appropriate call forward<ARGs>(args)... to implement perfect forwarding. He is now added.
Do you think this is not useful, here is a complete implementation of your factory using advanced redirection and varidict patterns that allow a certain number of parameters of specific types for a specific factory instance:
#include <string> #include <map> #include <memory> #include <utility> #include <iostream> using namespace std; template<typename BaseT, typename...ARGs> class Factory { public: static Factory* instance() { static Factory inst; return &inst; } template<typename T> void reg(const string& name) { m_stock[name].reset(new Creator<T>); } BaseT* create(const string& name, ARGs&&...args) { return m_stock[name]->create(forward<ARGs>(args)...); } private: struct ICreator { virtual BaseT* create(ARGs&&...) = 0; }; template<typename T> struct Creator : public ICreator { virtual BaseT* create(ARGs&&...args) override { return new T(forward<ARGs>(args)...); } }; std::map<string, std::unique_ptr<ICreator>> m_stock; }; template<typename BaseT, typename T, typename...ARGs> class Register { public: Register(const string& name) { auto instance = Factory<BaseT, ARGs...>::instance(); instance->template reg<T>(name); } }; struct C { virtual char const * whoAmI() const = 0; }; struct A : public C { A(int a1, int a2) { cout << "Creating A(" << a1 << ", " << a2 << ")" << endl; } virtual char const * whoAmI() const override { return "A"; } }; struct B : public C { B(int b1, int b2) { cout << "Creating B(" << b1 << ", " << b2 << ")" << endl; } B(int b1, int b2, int b3) { cout << "Creating B(" << b1 << ", " << b2 << ", " << b3 << ")" << endl; } virtual char const * whoAmI() const override { return "B"; } }; typedef int I; Register<C, A, I, I> a("a"); Register<C, B, I, I> b("b"); Register<C, B, I, I, I> b3("b"); int main() { C* a = Factory<C, I, I>::instance()->create("a", 1, 2); C* b = Factory<C, I, I>::instance()->create("b", 3, 4); C* b3 = Factory<C, I, I, I>::instance()->create("b", 5, 6, 7); cout << "I am a " << a->whoAmI() << endl; cout << "I am a " << b->whoAmI() << endl; cout << "I am a " << b3->whoAmI() << endl; return 0; }
Is this what you want? If you do not want to deal with function parameters, use the helper function of the template to display them for you like this:
template <typename BaseT, typename...ARGs> BaseT* create(const string& name, ARGs&&...args) { return Factory<C, ARGs...>::instance()->create(name, forward<ARGs>(args)...); } int main() { C* a = create<C>("a", 1, 2); C* b = create<C>("b", 3, 4); C* b3 = create<C>("b", 3, 4, 5); cout << "I am a " << a->whoAmI() << endl; cout << "I am a " << b->whoAmI() << endl; cout << "I am a " << b3->whoAmI() << endl; return 0; }
Which has an additional bonus that allows you to get multiple constructor signatures through the seemingly single-function API (it looks like only one, but actually N, where N is the number of different signatures that you allow). All of this can be viewed with this online demo .
You still have to use the same registration as before, but which can be shortened with a macro.
If this is not what you want, add additional details to your question.