如何创建基于通用模板的工厂
How to create a generic template based factory?
我正在使用c++98。我想创建一个基于模板的通用工厂,创建器可以不带参数来创建目标对象,或者带一个参数。
/*<class.h> begins
#ifndef INCLUDED_CLASS
#define INCLUDED_CLASS
#include <iostream>
#include <boost/shared_ptr.hpp>
class A
{
public:
A() { _a = 27; }
void print() const { std::cout << "A is " << _a << "." << std::endl; }
protected:
int _a;
};
typedef boost::shared_ptr<A> APtr;
class AA : public A
{
public:
void print() const { std::cout << "AA is " << _a << "!" << std::endl; }
};
class B
{
public:
B(double b) { _b = b; }
void print() const { std::cout << "B is " << _b << "." << std::endl; }
protected:
double _b;
};
typedef boost::shared_ptr<B> BPtr;
class BB : public B
{
public:
BB(double b) : B(b) {};
void print() const { std::cout << "BB is " << _b << "!" << std::endl; }
};
#endif
/*<class.h> ends
/*<factory.h> begins
#ifndef INCLUDED_FACTORY
#define INCLUDED_FACTORY
#include <map>
#include <string>
#include <boost/shared_ptr.hpp>
template<class bT, class pT=void>
class Creator
{
public:
virtual bT* create() = 0;
virtual bT* create(const pT* param) = 0;
};
template <class bT, class pT>
struct CreatorPtr
{
typedef boost::shared_ptr< Creator<bT> > type;
};
template <class bT, class cT, class pT>
class CreatorImpl : public Creator<bT, pT>
{
public:
virtual bT* create() { return new cT; }
virtual bT* create(const pT* param) { return new cT(param); }
};
template<class bT, class pT=void>
class Factory
{
public:
virtual bT* create(const std::string& name) const = 0;
virtual bT* create(const std::string& name, const pT* param) const = 0;
protected:
Factory() {}
Factory(const Factory&) {}
Factory &operator=(const Factory&) { return *this; }
void registerCreator(const std::string& name, typename CreatorPtr<bT, pT>::type creator)
{ _table_creator[name] = creator; }
typedef std::map<std::string, typename CreatorPtr<bT, pT>::type> tableCreator;
typedef typename tableCreator::const_iterator citerTc;
citerTc begin() const { return _table_creator.begin(); }
citerTc end() const { return _table_creator.end(); }
citerTc find(const std::string& name) const { return _table_creator.find(name); }
protected:
tableCreator _table_creator;
};
class A;
class EngineA : public Factory<A>
{
public:
virtual A* create(const std::string& name) const
{
citerTc it = find(name);
if (it != end() && it->second)
{
return it->second->create();
}
else
return (A*)NULL;
}
static Factory<A>& get()
{
static EngineA instance;
instance.registerEngine();
return instance;
}
private:
virtual A* create(const std::string& name, const void* param) const { return (A*)NULL; }
private:
virtual void registerEngine();
};
void EngineA::registerEngine()
{
CreatorPtr<A, void>::type AACreator(new CreatorImpl<A, AA, void>);
registerCreator("AA", AACreator);
}
class B;
class EngineB : public Factory<B, double>
{
public:
virtual B* create(const std::string& name, const double* value) const
{
citerTc it = find(name);
if (it != end() && it->second && value)
{
return it->second->create(value);
}
else
return (B*)NULL;
}
static Factory<B, double>& get()
{
static EngineB instance;
instance.registerEngine();
return instance;
}
private:
virtual B* create(const std::string& name) const { return (B*)NULL; }
private:
virtual void registerEngine();
};
void EngineB::registerEngine()
{
CreatorPtr<B, double>::type BBCreator(new CreatorImpl<B, BB, double>);
registerCreator("BB", BBCreator);
}
#endif
/*<factory.h> ends
/*<main.cpp> begins
#include <class.h>
#include <factory.h>
int main(void)
{
APtr a(EngineA::get().create("AA"));
if (a)
a->print();
double value = 35.7;
BPtr b(EngineB::get().create("BB",&value));
if (b)
b->print();
return 0;
}
/*<main.cpp> ends
编译错误如下:
....../boost//boost_1_46_1/include/boost/smart_ptr/shared_ptr.hpp: In constructor ‘boost::shared_ptr<T>::shared_ptr(Y*) [with Y = CreatorImpl<B, BB, double>, T = Creator<B, void>]’:
./factory.h:116: instantiated from here
....../boost//boost_1_46_1/include/boost/smart_ptr/shared_ptr.hpp:187: error: cannot convert ‘CreatorImpl<B, BB, double>*’ to ‘Creator<B, void>*’ in initialization
./factory.h: In member function ‘bT* CreatorImpl<bT, cT, pT>::create() [with bT = B, cT = BB, pT = double]’:
main.cpp:15: instantiated from here
./factory.h:27: error: no matching function for call to ‘BB::BB()’
./class.h:36: note: candidates are: BB::BB(double)
./class.h:34: note: BB::BB(const BB&)
./factory.h: In member function ‘bT* CreatorImpl<bT, cT, pT>::create(const pT*) [with bT = B, cT = BB, pT = double]’:
main.cpp:15: instantiated from here
./factory.h:28: error: no matching function for call to ‘BB::BB(const double*&)’
./class.h:36: note: candidates are: BB::BB(double)
./class.h:34: note: BB::BB(const BB&)
./factory.h: In member function ‘bT* CreatorImpl<bT, cT, pT>::create(const pT*) [with bT = A, cT = AA, pT = void]’:
main.cpp:15: instantiated from here
./factory.h:28: error: no matching function for call to ‘AA::AA(const void*&)’
./class.h:18: note: candidates are: AA::AA()
./class.h:18: note: AA::AA(const AA&)
make: *** [test] Error 1
有谁能帮我纠正错误吗?这是创建基于通用模板的工厂的好方法吗?
第一个错误:
typedef boost::shared_ptr< Creator<bT> > type;
您忘记传递pT:
typedef boost::shared_ptr< Creator<bT,pT> > type;
第二:virtual bT* create(const pT* param) { return new cT(param); }
要么在create中接受引用,要么将解引用的指针传递给构造函数:
virtual bT* create(const pT& param) { return new cT(param); } // and change the other parts of the code accordingly to accept reference instead of pointer
// or:
virtual bT* create(const pT* param) { return new cT(*param); }
更大的问题是,在这种方法中,两个版本的create都是为给定的cT生成的,并且由于缺少构造函数重载而无法编译。
对void进行专门化,只保留对create有意义的重载。这个方法可以工作:
#ifndef INCLUDED_CLASS
#define INCLUDED_CLASS
#include <iostream>
#include <boost/shared_ptr.hpp>
class A
{
public:
A() { _a = 27; }
void print() const { std::cout << "A is " << _a << "." << std::endl; }
protected:
int _a;
};
typedef boost::shared_ptr<A> APtr;
class AA : public A
{
public:
void print() const { std::cout << "AA is " << _a << "!" << std::endl; }
};
class B
{
public:
B(double b) { _b = b; }
void print() const { std::cout << "B is " << _b << "." << std::endl; }
protected:
double _b;
};
typedef boost::shared_ptr<B> BPtr;
class BB : public B
{
public:
BB(double b) : B(b) {};
void print() const { std::cout << "BB is " << _b << "!" << std::endl; }
};
#endif
// ----
#ifndef INCLUDED_FACTORY
#define INCLUDED_FACTORY
#include <map>
#include <string>
#include <boost/shared_ptr.hpp>
template<class bT, class pT = void>
class Creator
{
public:
virtual bT* create(const pT* param) = 0;
};
template<class bT>
class Creator<bT>
{
public:
virtual bT* create() = 0;
};
template <class bT, class pT = void>
struct CreatorPtr
{
typedef boost::shared_ptr< Creator<bT,pT> > type;
};
template <class bT>
struct CreatorPtr<bT>
{
typedef boost::shared_ptr< Creator<bT> > type;
};
template <class bT, class cT, class pT = void>
class CreatorImpl : public Creator<bT, pT>
{
public:
virtual bT* create(const pT* param) { return new cT(*param); }
};
template <class bT, class cT>
class CreatorImpl<bT,cT> : public Creator<bT>
{
public:
virtual bT* create() { return new cT; }
};
template<class CreatorPtrType>
class FactoryBase
{
protected:
FactoryBase() {}
FactoryBase(const FactoryBase&) {}
FactoryBase &operator=(const FactoryBase&) { return *this; }
void registerCreator(const std::string& name, CreatorPtrType creator)
{ _table_creator[name] = creator; }
typedef std::map<std::string, CreatorPtrType> tableCreator;
typedef typename tableCreator::const_iterator citerTc;
citerTc begin() const { return _table_creator.begin(); }
citerTc end() const { return _table_creator.end(); }
citerTc find(const std::string& name) const { return _table_creator.find(name); }
protected:
tableCreator _table_creator;
};
template<class bT, class pT = void>
class Factory : public FactoryBase<typename CreatorPtr<bT, pT>::type>
{
public:
virtual bT* create(const std::string& name, const pT* param) const = 0;
};
template<class bT>
class Factory<bT> : public FactoryBase<typename CreatorPtr<bT>::type>
{
public:
virtual bT* create(const std::string& name) const = 0;
};
class A;
class EngineA : public Factory<A>
{
public:
virtual A* create(const std::string& name) const
{
citerTc it = find(name);
if (it != end() && it->second)
{
return it->second->create();
}
else
return (A*)NULL;
}
static Factory<A>& get()
{
static EngineA instance;
instance.registerEngine();
return instance;
}
private:
virtual void registerEngine();
};
void EngineA::registerEngine()
{
CreatorPtr<A>::type AACreator(new CreatorImpl<A, AA>);
registerCreator("AA", AACreator);
}
class B;
class EngineB : public Factory<B, double>
{
public:
virtual B* create(const std::string& name, const double* value) const
{
citerTc it = find(name);
if (it != end() && it->second && value)
{
return it->second->create(value);
}
else
return (B*)NULL;
}
static Factory<B, double>& get()
{
static EngineB instance;
instance.registerEngine();
return instance;
}
private:
virtual void registerEngine();
};
void EngineB::registerEngine()
{
CreatorPtr<B, double>::type BBCreator(new CreatorImpl<B, BB, double>);
registerCreator("BB", BBCreator);
}
#endif
// ----
#include <class.h>
#include <factory.h>
int main(void)
{
APtr a(EngineA::get().create("AA"));
if (a)
a->print();
double value = 35.7;
BPtr b(EngineB::get().create("BB",&value));
if (b)
b->print();
return 0;
}
查看我的答案:https://stackoverflow.com/a/18253631/2288854
代码使用宏来生成一个最多包含N个参数的通用工厂模板。它不能在c++98中工作,但也许它可以给你一些想法
相关文章:
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- c++r值引用应用于函数指针
- 如果编译的源代码是特定于它编译的硬件的,我们如何分发它
- 如何仅使用对象名称打印特定于对象的成员
- 相当于LocaleMatcher的ICU4C
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 等<thing>效于char32_t
- 类似于strcat()的函数出现问题
- 使用Unique_ptr确保工厂中的对象唯一
- C++中用于结构的纯数组的类似于TableView/DataFrame的通用功能
- 实现通用工厂设计模式
- 具有多个构造函数的C 通用工厂
- 如何创建行为类似于流对象的工厂
- C++17 中的通用工厂机制
- 如何实现支持模板协方差的通用工厂
- 如何使用指向通用模板类的指针来访问依赖于模板参数类型的成员函数
- 如何创建基于通用模板的工厂
- 类似于嵌套互斥锁,但更通用
- 利用boost变体创建具有boost::mpl::for_each的通用工厂方法
- 工厂模式中特定于子类的访问