c++派生类型的自动工厂注册
c++ automatic factory registration of derived types
像我之前的许多人一样,我正在尝试让我的派生类型自动向我的工厂注册。我通读了许多问题,并试着把注意力集中在我没有发现的地方。
除了自动注册外,我的一切都很顺利。
我的目标:
- 自动注册我的基类的任何派生类base
- 只有我标记为可注册的类
- 不仅仅是Base的直接子类
- 例如:基础->设备->相机->网络摄像头
- 这将使使用本问题中描述的CRTP变得困难
- 我想要注册的类的最小更改-dummies证明
- 与宏相比,更喜欢使用注册器类
- 就像这个问题一样,但我不确定这是否取决于CRTP
我所拥有的:
template <class T>
class abstract_factory
{
public:
template < typename Tsub > static void register_class();
static T* create( const std::string& name );
private:
// allocator<T> is a helper class to create a pointer of correct type
static std::map<std::string, boost::shared_ptr<allocator<T> > > s_map;
};
- 模板化抽象工厂,std::string为键类型
- 抽象工厂具有所有成员和方法static
- 类名使用typeid自动恢复(注册时不需要文本名称)
- 呼叫注册:
abstract_factory<Base>::register_class<MyDerived>();
我尝试了什么(或想尝试但不知道如何正确操作):
registrator<Derived> class
:模板类,在Derived.cpp
中静态实例化,应在其构造函数中调用abstract_factory::register_class<Derived>()
- 从不被调用或实例化
- 如果我在
main()
中创建一个Derived
的实例,这就起作用了->但有点违背目的
- 在每个
Derived.hpp
中声明一个简单的静态变量,并再次使用Derived.cpp
->中的静态注册方法设置它,永远不会被调用 - 让
abstract_factory
成为一个真正的单例,而不是让所有东西都是静态的
可以使用任何建议,无论大小,thanx。
我使用带有成员的singleton进行注册,基本上是:
template< typename KeyType, typename ProductCreatorType >
class Factory
{
typedef boost::unordered_map< KeyType, ProductCreatorType > CreatorMap;
...
};
使用Loki,我就有了这样的东西:
typedef Loki::SingletonHolder< Factory< StringHash, boost::function< boost::shared_ptr< SomeBase >( const SomeSource& ) > >, Loki::CreateStatic > SomeFactory;
注册通常使用宏来完成,例如:
#define REGISTER_SOME_FACTORY( type ) static bool BOOST_PP_CAT( type, __regged ) = SomeFactory::Instance().RegisterCreator( BOOST_PP_STRINGIZE( type ), boost::bind( &boost::make_shared< type >, _1 ) );
这种设置有很多优点:
- 适用于例如boost::shared_ptr<>
- 不需要为所有注册需求维护一个庞大的文件
- 与创作者相处非常灵活,任何事情都很顺利
- 该宏涵盖了最常见的用例,同时为替代方案敞开了大门
调用.cpp文件中的宏就足以在静态初始化期间获得启动时注册的类型。当类型注册是静态库的一部分时,这种方法非常有效,在这种情况下,它不会包含在二进制文件中。将注册作为库的一部分进行编译的唯一解决方案是,有一个巨大的文件作为某种初始化例程的一部分显式地进行注册。相反,我现在所做的是为我的lib创建一个客户端文件夹,用户将其作为二进制构建的一部分。
从你的要求列表中,我相信这满足了除了使用注册器类之外的所有要求。
---注册.h---
#include <iostream>
#include <typeinfo>
#include <set>
#include <string>
using namespace std;
template<class T>
struct registrar {
struct proxy { inline proxy();};
static proxy p;
};
template<class T> typename registrar<T>::proxy registrar<T>::p;
struct factory {
template <typename T> static T* create() {
registrar<T>::p;
return new T();
}
};
set<string> & types();
template<typename T>
registrar<T>::proxy::proxy() { types().insert(typeid(T).name());}
---注册.cpp---
#include "registration.h"
#include <boost/foreach.hpp>
set<string> & types() {static set<string> types; return types;}
int main() {
BOOST_FOREACH(const string & s, types()) { cout<<s<<"n";}
factory::create<int>();
factory::create<double>();
factory::create<bool>();
return 0;
}
---registration_ext.cpp---
#include "registration.h"
class myclass {};
void phony() {
factory::create<double>();
factory::create<myclass>();
}
然后用编译
$ g++ registration.cpp registration_ext.cpp -o registration
运行时:
$ ./registration
7myclass
b
d
i
所以,它似乎在调用main之前就已经注册了类。
编辑:我注意到这个解决方案依赖于实现。根据3.6.2,C++标准规定:
它是由实现定义的具有静态存储持续时间的非局部变量在主语句的第一个语句。如果初始化推迟到在main的第一个语句之后的时间点,它应发生在中定义的任何函数或变量的第一次odr使用(3.2)与要初始化的变量相同的转换单元。
相关文章:
- 无法将结构注册为增强几何体3D点
- 如何使用AngelScript注册SFML Vector2运算符
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 使用Unique_ptr确保工厂中的对象唯一
- 在遍历处理程序的向量时注册和注销处理程序
- 带有继承的C++工厂
- 有没有任务栏API可以立即应用注册表更改
- C++库和自注册类:客户端应用程序中的工厂映射为空
- 注册对对象工厂的调用会导致段错误
- 基于模板的自注册工厂,具有现代 CMake 构建和源插入检测
- CRTP自动注册工厂(静态初始化顺序失败)
- 当c++对象位于单独的共享库中时,我如何向工厂自动注册这些对象
- 链接自注册的抽象工厂
- c++派生类型的自动工厂注册
- 编译时插件/具有独立模块约束的自动工厂注册
- 由于静态链接(用于汽车工厂注册),c++丢失了静态函数调用
- c++中类模板的自动编译时工厂注册
- c++工厂模式使用模板进行自注册
- 通过元编程或其他方式自动注册dll模块中的静态对象工厂
- 实现一个在C++中向其注册非静态成员函数的工厂