Templates C++;:可以调用任何构造函数的通用工厂?
我正在尝试编写一个factory类,它将有一个如下所示的标准接口:Templates C++;:可以调用任何构造函数的通用工厂?,templates,c++11,factory,type-erasure,Templates,C++11,Factory,Type Erasure,我正在尝试编写一个factory类,它将有一个如下所示的标准接口: Register<MyBase, MyDerived> g_regDerived("myderived"); // register to factory 这里的问题是,一旦删除创建对象的类型,就不能再传递任意模板转发参数,因为需要通过虚拟函数传递它们 这个问题的答案是: 讨论了一些类似的问题,但答案是通过一个特定于每个派生类的函数。我想直接使用类构造函数,而不必编写create()函数。我不知道您为什么不喜欢
Register<MyBase, MyDerived> g_regDerived("myderived"); // register to factory
这里的问题是,一旦删除创建对象的类型,就不能再传递任意模板转发参数,因为需要通过虚拟函数传递它们
这个问题的答案是:讨论了一些类似的问题,但答案是通过一个特定于每个派生类的函数。我想直接使用类构造函数,而不必编写
create()
函数。我不知道您为什么不喜欢编写create()
函数。这里是我实现的一个
#include <iostream>
#include <utility>
using namespace std;
class C
{
public:
virtual char const* whoAmI() const = 0;
};
class A : public C
{
public:
A(int a1)
{
cout << "A(" << a1 << ")" << endl;
}
A(float a1)
{
cout << "A(" << a1 << ")" << endl;
}
virtual char const* whoAmI() const override
{
return "A";
}
};
class B : public C
{
public:
B(int a1)
{
cout << "B(" << a1 << ")" << endl;
}
B(float a1)
{
cout << "B(" << a1 << ")" << endl;
}
virtual char const* whoAmI() const override
{
return "B";
}
};
template<typename BASET>
class Factory
{
public:
// could use a is_base type trait test here
template <typename T, typename...ARGs>
static BASET* create(ARGs&&...args)
{
return new T(forward<ARGs>(args)...);
}
};
int main()
{
Factory<C> factory;
C* a = factory.create<A>(1);
C* b = factory.create<B>(1.0f);
cout << a->whoAmI() << endl;
cout << b->whoAmI() << endl;
return 0;
}
#包括
#包括
使用名称空间std;
C类
{
公众:
虚拟字符常量*whoAmI()常量=0;
};
A类:公共C类
{
公众:
A(int a1)
{
我是否认为完美地实现这一点是不可能的;函数的参数实际上是编译时的,与其他一些语言(如Java或C#)相比(它们可以通过反射动态调用函数)当然C++有编译时的反射,但是你想动态调用函数。我建议模仿这些运行时的反射:你可以使用一些东西,比如<代码>空隙*创建(const STD::vector and PARAMS);< /Cord>。你也可以提供宏或模板来帮助客户端创建这个“创建”。函数。如果通过引入一个config
类来允许某种类型的动态初始化,我得到的结果会简单得多。该类基本上是一个boost::any
列表,并且始终允许作为要创建的类的单个参数。create()有什么问题
function?@Adrian你可以假设我的问题有很好的理由。用无用的答案对我来说毫无帮助是非常不礼貌的。我试着不去假设,但如果没有更多的信息,你可能正在尝试做一些不必要和/或适得其反的事情。说明你的理由s可能会帮助人们想出你没有想到的解决方案,因为你离问题太近了。作为一个拥有36k代表的人,你应该知道这一点。至于你说我粗鲁是因为你认为我在发垃圾邮件是粗鲁的。但是,如果你想得到更好的答案,那么就提出一个对整个社区更有用的问题。谢谢你用一个无用的答案对问题进行垃圾邮件处理。现在请删除它。好吧,最初的答案是无用的,因为它没有解决问题,部分地陈述了它。编辑的答案实际上似乎是有效的。你正在为每一组参数实例化Factory,所以Factory不再是一个真正的单例。但是我可以类似于元工厂的东西,它将引用所有不同的工厂,这些工厂将是一个单体(这对我来说很重要,因为一个无关的原因,我不想描述)。谢谢你,我道歉:)@shoosh,最初的答案是指你想去的方向。我不想为你做所有的工作
template<typename BaseT>
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) {
return m_stock[name]->create();
}
private:
struct ICreator {
virtual BaseT* create() = 0;
};
template<typename T>
struct Creator : public ICreator {
virtual BaseT* create() {
return new T;
}
};
std::map<string, std::unique_ptr<ICreator>> m_stock;
};
template<typename BaseT, typename T>
class Register {
public:
Register(const QString& name) {
Factory<BaseT>::instance()->reg<T>(name);
}
};
#include <iostream>
#include <utility>
using namespace std;
class C
{
public:
virtual char const* whoAmI() const = 0;
};
class A : public C
{
public:
A(int a1)
{
cout << "A(" << a1 << ")" << endl;
}
A(float a1)
{
cout << "A(" << a1 << ")" << endl;
}
virtual char const* whoAmI() const override
{
return "A";
}
};
class B : public C
{
public:
B(int a1)
{
cout << "B(" << a1 << ")" << endl;
}
B(float a1)
{
cout << "B(" << a1 << ")" << endl;
}
virtual char const* whoAmI() const override
{
return "B";
}
};
template<typename BASET>
class Factory
{
public:
// could use a is_base type trait test here
template <typename T, typename...ARGs>
static BASET* create(ARGs&&...args)
{
return new T(forward<ARGs>(args)...);
}
};
int main()
{
Factory<C> factory;
C* a = factory.create<A>(1);
C* b = factory.create<B>(1.0f);
cout << a->whoAmI() << endl;
cout << b->whoAmI() << endl;
return 0;
}
#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;
}
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;
}