c++11 模板工厂模式和带参数的构造函数

标签 c++ c++11 factory

我正在尝试创建一个具有自动注册功能的 C++11 模板工厂, 我几乎遵循了这个:http://www.drdobbs.com/conversations-abstract-factory-template/184403786

所以我有一个像这样的AFactory:

template<class BaseType, typename IDKey = std::string>
class AFactory : public Singleton<AFactory<BaseType, IDKey>>
{
friend class Singleton<AFactory>;

private:
    typedef std::unique_ptr<BaseType>(*typeCreator)();

public:
    AFactory() = default;
    ~AFactory() = default;

    AFactory(const AFactory&) = delete;
    AFactory& operator=(const AFactory&) = delete;

    void registerNewClass(const IDKey& key, const typeCreator& creator)
    {
        _registerTypes.insert({key, creator});
    };

    template<typename... Args>
    std::unique_ptr<BaseType> create(const IDKey& key, Args&&... args) const
    {
        return (_registerTypes.at(key))(std::forward<Args>(args)...);
    };

private:
    std::unordered_map<IDKey, typeCreator> _registerTypes;
};

还有这样的注册类:

template<class BaseType, class RealType, typename IDKey = std::string>
class AFactoryRegistration
{
public:
    AFactoryRegistration(const IDKey& key)
    {
        AFactory<BaseType>::instance().registerNewClass(key, &instancier);
    };

    ~AFactoryRegistration() = default;
    AFactoryRegistration(const AFactoryRegistration&) = delete;
    AFactoryRegistration& operator=(const AFactoryRegistration&) = delete;

    static std::unique_ptr<BaseType> instancier()
    {
        return std::unique_ptr<BaseType>(new RealType());
    };
};

但是对于采用构造参数的类,我仍然存在问题。 例如,如果我有一个类:

class Point : public stuff
{
public:
Point(int x, int y);
/*...*/

};

如何将类 Point 注册到采用构造函数 Point(int x, int y) 的工厂?

最佳答案

哇。四年前的问题。也许 std::any 会有所帮助。您可以在 std::any 中存储任何内容。

any_cast 有点棘手。

参见下面的示例:

#include <iostream>
#include <map>
#include <utility>
#include <any>


// Some demo classes ----------------------------------------------------------------------------------
struct Base {
    Base(int d) : data(d) {};
    virtual ~Base() { std::cout << "Destructor Base\n"; }
    virtual void print() { std::cout << "Print Base\n"; }
    int data{};
};
struct Child1 : public Base {
    Child1(int d, std::string s) : Base(d) { std::cout << "Constructor Child1 " << d << " " << s << "\n"; }
    virtual ~Child1() { std::cout << "Destructor Child1\n"; }
    virtual void print() { std::cout << "Print Child1: " << data << "\n"; }
};
struct Child2 : public Base {
    Child2(int d, char c, long l) : Base(d) { std::cout << "Constructor Child2 " << d << " " << c << " " << l << "\n"; }
    virtual ~Child2() { std::cout << "Destructor Child2\n"; }
    virtual void print() { std::cout << "Print Child2: " << data << "\n"; }
};
struct Child3 : public Base {
    Child3(int d, long l, char c, std::string s) : Base(d) { std::cout << "Constructor Child3 " << d << " " << l << " " << c << " " << s << "\n"; }
    virtual ~Child3() { std::cout << "Destructor Child3\n"; }
    virtual void print() { std::cout << "Print Child3: " << data << "\n"; }
};



using UPTRB = std::unique_ptr<Base>;


template <class Child, typename ...Args>
UPTRB createClass(Args...args) { return std::make_unique<Child>(args...); }

// The Factory ----------------------------------------------------------------------------------------
template <class Key, class Object>
class Factory
{
    std::map<Key, std::any> selector;
public:
    Factory() : selector() {}
    Factory(std::initializer_list<std::pair<const Key, std::any>> il) : selector(il) {}

    template<typename Function>
    void add(Key key, Function&& someFunction) { selector[key] = std::any(someFunction); };

    template <typename ... Args>
    Object create(Key key, Args ... args) {
        if (selector.find(key) != selector.end()) {
            return std::any_cast<std::add_pointer_t<Object(Args ...)>>(selector[key])(args...);
        }
        else return nullptr;
    }
};

int main()
{
    Factory<int, UPTRB> factory{
        {1, createClass<Child1, int, std::string>},
        {2, createClass<Child2, int, char, long>}
    };
    factory.add(3, createClass<Child3, int, long, char, std::string>);


    // Some test values
    std::string s1(" Hello1 "); std::string s3(" Hello3 ");
    int i = 1;  const int ci = 1;   int& ri = i;    const int& cri = i;   int&& rri = 1;

    UPTRB b1 = factory.create(1, 1, s1);
    UPTRB b2 = factory.create(2, 2, '2', 2L);
    UPTRB b3 = factory.create(3, 3, 3L, '3', s3);

    b1->print();
    b2->print();
    b3->print();
    b1 = factory.create(2, 4, '4', 4L);
    b1->print();
    return 0;
}

你可以进一步概括它。但 then 只是创建者函数的包装。

关于c++11 模板工厂模式和带参数的构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26770115/

相关文章:

c++ - 无法编辑 TADOTable 中的数据

c++ - std::map::插入异常

c++ - 比较不同版本库性能的最佳方法

C++:使用Boost MultiIndex确定指针类型的类

c++ - std::vector of objects/pointers/smart pointers to pass objects (bus error: 10)?

c++ - 为什么默认情况下 C++1 1's lambda require "mutable"keyword 用于按值捕获?

c++ - 如何使用带参数化构造函数的类的比较对象来声明 STL 集

javascript - Angular 工厂,如何彻底改变结果

java - 将具体工厂传递给抽象工厂类 - java

c# - 你如何在工厂中实现构造函数注入(inject)?