C++ 如何将参数传递给工厂元素构造函数?

C++ 如何将参数传递给工厂元素构造函数?,c++,boost,C++,Boost,我有一个类树,我想存储在织物中。我看到了如何为具有空构造函数或预定义构造函数的元素实现结构,但我看不到如何使不具有预定义构造函数参数的元素得以使用。我们也这么说。我们的工厂是这样的: 工厂。水电站: #include <unordered_map> #include <string> template<class BaseType, class BaseTypeCode> class Factory { public: typedef BaseTyp

我有一个类树,我想存储在织物中。我看到了如何为具有空构造函数或预定义构造函数的元素实现结构,但我看不到如何使不具有预定义构造函数参数的元素得以使用。我们也这么说。我们的工厂是这样的:

工厂。水电站:

#include <unordered_map>
#include <string>

template<class BaseType, class BaseTypeCode>
class Factory {
public:
    typedef BaseType * (*base_creator_fn)();
    typedef std::unordered_map<BaseTypeCode, base_creator_fn> registry_map;

    static registry_map & registry() {
        static registry_map impl;
        return impl;
    }

    static BaseType * instantiate(BaseTypeCode const & name) {
        auto it = registry().find(name);
        return it == registry().end() ? nullptr : (it->second)();
    }

    virtual ~Factory() = default;        
};

template<class BaseClass,  class BaseTypeCode>
struct Registrar {
    Registrar(BaseTypeCode name, Factory<BaseClass>::base_creator_fn func) {
        Factory<BaseClass>::registry()[name] = func;
    }
};
#include "Factory.hpp"

enum ExampleTypeCode { ExampleTypeCode_Simple = 1 };

class ExampleBase {
    virtual ~ExampleBase(){}
};

class Example : public ExampleBase {
    Example(int i) {}
    virtual ~Example(){}

    static Registrar<ExampleBase, ExampleTypeCode> registrar;
};
#include <boost/bind.hpp>
#include <boost/lambda.hpp>
#include "Example.hpp"

Registrar<Example, ExampleTypeCode> Example::registrar(ExampleTypeCode_Simple, boost::bind(boost::lambda::new_ptr<Example>, _firstVarArg));
示例。cpp:

#include <unordered_map>
#include <string>

template<class BaseType, class BaseTypeCode>
class Factory {
public:
    typedef BaseType * (*base_creator_fn)();
    typedef std::unordered_map<BaseTypeCode, base_creator_fn> registry_map;

    static registry_map & registry() {
        static registry_map impl;
        return impl;
    }

    static BaseType * instantiate(BaseTypeCode const & name) {
        auto it = registry().find(name);
        return it == registry().end() ? nullptr : (it->second)();
    }

    virtual ~Factory() = default;        
};

template<class BaseClass,  class BaseTypeCode>
struct Registrar {
    Registrar(BaseTypeCode name, Factory<BaseClass>::base_creator_fn func) {
        Factory<BaseClass>::registry()[name] = func;
    }
};
#include "Factory.hpp"

enum ExampleTypeCode { ExampleTypeCode_Simple = 1 };

class ExampleBase {
    virtual ~ExampleBase(){}
};

class Example : public ExampleBase {
    Example(int i) {}
    virtual ~Example(){}

    static Registrar<ExampleBase, ExampleTypeCode> registrar;
};
#include <boost/bind.hpp>
#include <boost/lambda.hpp>
#include "Example.hpp"

Registrar<Example, ExampleTypeCode> Example::registrar(ExampleTypeCode_Simple, boost::bind(boost::lambda::new_ptr<Example>, _firstVarArg));

我的主要编译目标是最新的GCC和Visual Studio 2012以及最新的service pack,因此C++11子集还非常有限。

您可以将工厂与构建器结合起来,以获得所需的行为。构建器将保存这些参数

template<class BaseType, class BaseTypeCode, class BaseTypeBuilder>
class Factory {
public:
    typedef BaseType * (*base_creator_fn)(BaseTypeBuilder const &);
    //...
    static BaseType * instantiate(BaseTypeCode const & name,
                                  BaseTypeBuilder const & builder
                                  = BaseTypeBuilder()) {
        auto it = registry().find(name);
        return it == registry().end() ? nullptr : (it->second)(builder);
    }

    virtual ~Factory() = default;        
};

可变模板可以帮助这里。我使用了
void*
作为第二种类型的
registry\u map
,这样我们就可以在注册表中存储任何类型的函数。下面是一段演示基本思想的简短代码:

class Base
{
public:
    typedef std::unordered_map<std::string, void*> registry_map;

    virtual ~Base() = default;

    static registry_map & registry()
    {
        static registry_map impl;
        return impl;
    }
    template<typename ...T>
    static Base * instantiate(std::string const & name, T&&...args)
    {
        auto it = registry().find(name);
        if ( it == registry().end()) return 0;
        typedef Base* (*create_type)(T...);
        auto create_fun = reinterpret_cast<create_type>(it->second);
        return create_fun(args...);
    }
    virtual void f() = 0;
};

struct Registrar
{
    template<typename F>
    Registrar(std::string name, F func)
    {
        Base::registry()[name] = reinterpret_cast<void*>(func);
    }
};

希望有帮助。:-)

我想你必须使用某种类型的类型擦除。你能用C++11吗?顺便说一句,
示例
不是从
ExampleBase
派生出来的。而且,
Example.cpp
文件中似乎有输入错误。请先解决这些问题。@Nswaz:修复了一些打字错误,VS2012主要问题。。。所以一些C++11还不是全部。你好,回答,谢谢你的想法!您能说明在C++03/C中如何使用变长参数进行变长吗?@DuckQueen:要支持C++03中的变长参数,您需要在代码中添加重载函数模板。只要看看当前的代码是如何工作的,这将让您了解如何在C++03中完成它。
DerivedExample
AnotherExample. a = 10, b = Mahfuza