有时候我们需要将类型与一些数据进行绑定,例如我们一般通过单例,将字符串与一个函数关联(一般称之为注册),之后通过字符串创建相关联的对象

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>();

C++模板之类型与数据绑定的更多相关文章

  1. C++11 图说VS2013下的引用叠加规则和模板参数类型推导规则

    背景:    最近在学习C++STL,出于偶然,在C++Reference上看到了vector下的emplace_back函数,不想由此引发了一系列的“探索”,于是就有了现在这篇博文. 前言:     ...

  2. C++模板参数类型(转载)

    实际上有三种类型模板参数:类型模板参数.无类型模板参数和模板模板参数(以模板作为模板的参数). .类型模板参数 类型模板参数是我们使用模板的主要目的.我们可以定义多个类型模板参数: template& ...

  3. 《深入实践C++模板编程》之三——模板参数类型详解

    非类型模板参数 和 模板型模板参数 整数以及枚举类型:指向对象或者函数的指针:对对象或函数的引用:指向对象成员的指针.统称为非类型模板参数. 模板型模板参数,是指模板参数还可以是一个模板.   1.整 ...

  4. AngularJS开发指南12:AngularJS的模板,CSS,数据绑定详解

    模板 AngularJS模板是一种声明式的规则.它包含了模型和控制器的信息,最后会被渲染成用户在浏览器中看到的视图.它是静态的DOM,包含HTML,CSS和AngularJS指定的元素和属性.Angu ...

  5. c++ 模板 指针类型偏特化

    一步步来,先简单点. 目标:我们要实现一个模板类,例化后,可以通过get_val获取到值,通过get_ptr获取到指针.具体什么意思结合例子来看看吧. 例子: struct A{ int data; ...

  6. c++ 使用模板按类型统计stl多维容器中元素的数量

    struct ItemCounter{template<typename T1, typename T2, typename = typename std::enable_if<!std: ...

  7. C++11 引用叠加规则和模板参数类型推导规则

    http://zm8.sm-img2.com/?src=http%3A%2F%2F***%2FArticle%2F38320&uid=57422b713ac761e653af7b327bfd9 ...

  8. FlatBuffers入门

    1.下载flatbuffers 从https://github.com/google/flatbuffers地址下载flatbuffers-master.zip文件. 2.编译flatbuffers ...

  9. GridView的七种数据绑定列的类型

    1.BoundField 用于显示普通文本,是默认的数据绑定列的类型,一般自动生成的列就是该类型,需要注意是DataFormatString属性,该属性可以设置显示的格式,常见格式有:{0:C} 设置 ...

随机推荐

  1. 初始化git

    git config --global user.name "Firstname Lastname" git config --global user.email "yo ...

  2. PHP字符串转义

    与PHP字符串转义相关的配置和函数如下: 1.magic_quotes_runtime 2.magic_quotes_gpc 3.addslashes()和stripslashes() 4.mysql ...

  3. UNIX基础--进程和守护进程

    进程和守护进程 Processes and Daemons 进程(Processes) FreeBSD 是一个多任务操作系统. 这就意味着好像一次可以运行一个以上的程序. 每个占用一定时间运行的程序就 ...

  4. action解耦方式

    ServletAction方式,必须要有Servlet容器作支持 package com.hanqi.action; import javax.servlet.ServletContext; impo ...

  5. kubernetes port nodePort targetPort 理解

    port The port that the service is exposed on the service's cluster ip (virsual ip). Port is the serv ...

  6. linux下安装tomcat,并设置自动启动

    在linux系统下,设置某个服务自启动的话,需要在/etc/rcX.d下挂载,还要在/etc/init.d/下写启动脚本的 在/etc/init.d/下新建一个文件tomcat(需要在root权限下操 ...

  7. Python学习之旅--第二周--python基础

    一.什么是pyc? 1.Python是解释性语言,那么.pyc是什么文件? 2.解释性语言和编译型语言区别:    计算机是不能够识别高级语言的,所以当我们运行一个高级别语言程序时,就需要一个&quo ...

  8. Hadoop datanode 磁盘自动化处理

    新集群的 datanode 磁盘自动化处理工具开工在即.

  9. C++中int转为char 以及int 转为string和string 转int和空格分隔字符串

    1.对于int 转为char 直接上代码: 正确做法: void toChar(int b) { char u; ]; _itoa( b, buffer, ); //正确解法一 u = buffer[ ...

  10. tflearn save模型异常

    存储模型始终无法形成单个文件,最初以为是机器中间断电\休眠引起的,重复了3次之后,发现这个问题一直存在.(每一次都要跑8~9个小时啊,摔...) 解决办法:tensorflow的版本回退到0.11版 ...