C++模板之类型与数据绑定
有时候我们需要将类型与一些数据进行绑定,例如我们一般通过单例,将字符串与一个函数关联(一般称之为注册),之后通过字符串创建相关联的对象
class A { public: static A* Create() { return new A(); } };
然后像这样:
Instance::Register("A", A::Create); A* a = Instance::Create("A");
用字符串进行绑定,不是很方便,如果字符串拼写错了,在整个编译期不会有任何提示,而且字符串是没有代码自动提示的,这样出错率大大增加了,当然你可以复制/粘贴;如果我们能够将一个类型与数据进行绑定,通过类型获取与之相关的数据,一是类型有代码自动提示的(一般拼写前几个字符就可以完成整个输入),及时你自己拼写出错了,没有定义这个类型,编译器编译时也会报错。这里我们使用函数模板,理论上不同的类型,会实例化为不同的函数,我们可以使用函数地址作为标识这个类型的key。
TypeBind.h
#ifndef _Type_Bind_H_ #define _Type_Bind_H_ #include <assert.h> #include <map> template<class _Value> class TypeBind { public: template<class _Type> void bind(_Value value) { m_map.insert(std::make_pair(TypeDefine<_Type>, value)); } template<class _Type> _Value& find() { std::map<TypeDefineIndifiry, _Value>::iterator iter = m_map.find(TypeDefine<_Type>); assert(iter != m_map.end()); return iter->second; } private: template<class T> static void TypeDefine(char _ch) { static char ch = _ch; } typedef void(*TypeDefineIndifiry)(); std::map<TypeDefineIndifiry, _Value> m_map; }; #endif
这里我们使用的是
“template<class T> static void TypeDefine(char _ch) { static char ch = _ch; }“函数
而没有使用
"template<class T> static void TypeDefine() {}"函数
原因是生成Release版本时,编译器会进行优化,如果函数的内容是一致的,最后只会生成一个函数(函数的名称不相同,但是内容是一样,也是相同的结果),如果所有类型的函数地址是一致的,就无法使用给每个类型一个标识(函数地址)
test.cpp
#include "TypeBind.h" typedef void*(*CreateCallback)(); // 创建函数的指针 class ObjectCreateFactory { public: /** 注册 * @T 绑定的类型 * @callback 对象创建函数 */ template<class T> void Register(CreateCallback callback) { m_map.bind<T>(callback); } /** 创建对象 * @T 创建对象的类型 * @return 创建的对象 */ template<class T> T* Create() { CreateCallback callback = m_map.find<T>(); return (T*)callback(); } static ObjectCreateFactory& Instance() { static ObjectCreateFactory* factory = nullptr; if (!factory) factory = new ObjectCreateFactory(); return *factory; } private: ObjectCreateFactory() {} TypeBind<CreateCallback> m_map; }; class A { public: static A* Create() { return new A(); } }; class B { public: static B* Create() { return new B(); } }; // 注册 ObjectCreateFactory::Instance().Register<A>((CreateCallback)A::Create); ObjectCreateFactory::Instance().Register<B>((CreateCallback)B::Create); // 创建 A* a = ObjectCreateFactory::Instance().Create<A>(); B* b = ObjectCreateFactory::Instance().Create<B>();