#ifndef _ZTC_DELEGATE_H_
#define _ZTC_DELEGATE_H_ #include <vector>
#include <functional> ///////////////////////////////////////////////
// C++ 使用 可变参数模板类, 来实现
// C#中的 委托
// Anchor: ztc
// Date : 2014-01-10
/////////////////////////////////////////////// template<typename R, typename ...Args>
class Delegate {
public:
template<typename U>
Delegate& operator += (const U &func) {
funcList.push_back(std::function<R(Args...)>(func));
funcPointers.push_back((void*)&func);
return *this;
} template<typename U>
Delegate& operator -= (const U &func) {
int i = -;
for (auto iter = funcPointers.begin(); iter != funcPointers.end(); iter++) {
i++;
if (*iter == (void*)&func) {
funcPointers.erase(iter);
funcList.erase(funcList.begin() + i);
break;
}
}
return *this;
} std::vector<R> operator()(Args...args) {
std::vector<R> ret;
for (auto f : funcList) {
ret.push_back(f(args...));
}
return ret;
}
private:
std::vector<std::function<R(Args...)>> funcList;
std::vector<void*> funcPointers;
}; template<typename ...Args>
class Delegate<void, Args...> {
public:
template<typename U>
Delegate& operator += (const U &func) {
std::cout << "注册方法 " << typeid(func).name() << std::endl;
funcList.push_back(std::function<void(Args...)>(func));
funcPointers.push_back((void*)&func);
return *this;
} template<typename U>
Delegate& operator -= (const U &func) {
std::cout << "卸载方法 " << typeid(func).name() << std::endl;
int i = -;
for (auto iter = funcPointers.begin(); iter != funcPointers.end(); iter++) {
i++;
if (*iter == (void*)&func) {
funcPointers.erase(iter);
funcList.erase(funcList.begin() + i);
break;
}
}
return *this;
} void operator() (Args... args) {
for (auto f : funcList) {
f(args...);
}
}
private:
std::vector<std::function<void(Args...)>> funcList;
std::vector<void*> funcPointers;
}; #endif // _ZTC_DELEGATE_H_

ztc_Delegate.hpp

 #include <iostream>
#include "ztc_Delegate.hpp"   // 普通函数
int foo(int a, int b) {
return a * a + b * b;
}   // 普通无参无返回函数
void kaoo() {
std::cout << "kaooooooo" << std::endl;
}
void kaoo2() {
std::cout << "kaooooo22222oo" << std::endl;
}   // 类成员函数
class Test {
public:
void funcInClass() {
std::cout << "Function In Class" << std::endl;
}
}; int main() {
// 定义事件 有返回值
Delegate<int, int, int> OnSomething;
// 定义事件 无返回值
Delegate<void> OnKao; // 注册方法
OnSomething += [](int a, int b) {return a + b; };
OnSomething += [](int a, int b) {return a * b; };
OnSomething += foo; // 类的成员函数 需要 使用 Bind
Test c;
auto cf = std::bind(&Test::funcInClass, c); // 注册类成员函数
OnKao += cf;
// 注册普通函数
OnKao += kaoo;
OnKao += kaoo2;
// 调用事件
OnKao();
// 卸载类成员函数
OnKao -= cf;
// 制裁普通函数
OnKao -= kaoo;
// 调用方法
OnKao(); // 调用事件 得到 结果
auto ret = OnSomething(, ); // 显示结果
for (auto r : ret) {
std::cout << r << std::endl;
} return ;
}

C++ 0x 使用可变参数模板类 实现 C# 的委托机制的更多相关文章

  1. c++11 可变参数模板类

    c++11 可变参数模板类 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #inc ...

  2. 泛化之美 —— C++11 可变参数模板的妙用

    概述 首先这篇文章出自博客园作者:[qicosmos ],我对本文的实例代码进行了学习.思考和整理纠正,理清了文章的全部细节,觉得这是一篇让我受益匪浅的文章.之所以会接触「可变参数模板」这部分的内容, ...

  3. 第26课 可变参数模板(7)_any和variant类的实现

    1. any类的实现 (1)any类: ①是一个特殊的,只能容纳一个元素的容器,它可以擦除类型,可以将何任类型的值赋值给它. ②使用时,需要根据实际类型将any对象转换为实际的对象. (2)实现any ...

  4. C++反射机制:可变参数模板实现C++反射(使用C++11的新特性--可变模版参数,只根据类的名字(字符串)创建类的实例。在Nebula高性能网络框架中大量应用)

    1. 概要   本文描述一个通过C++可变参数模板实现C++反射机制的方法.该方法非常实用,在Nebula高性能网络框架中大量应用,实现了非常强大的动态加载动态创建功能.Nebula框架在码云的仓库地 ...

  5. C++反射机制:可变参数模板实现C++反射

    1. 概要   本文描述一个通过C++可变参数模板实现C++反射机制的方法.该方法非常实用,在Nebula高性能网络框架中大量应用,实现了非常强大的动态加载动态创建功能.Nebula框架在Github ...

  6. 第27课 可变参数模板(8)_TupleHelper

    1. TupleHelper的主要功能 (1)打印:由于tuple中的元素是可变参数模板,外部并不知道内部到底是什么数据,有时调试时需要知道其具体值,希望能打印出tuple中所有的元素值. (2)根据 ...

  7. 第24课 可变参数模板(5)_DllHelper和lambda链式调用

    1. dll帮助类 (1)dll的动态链接 ①传统的调用方式:先调用LoadLibrary来加载dll,再定义函数指针类型,接着调用GetProcAddress获取函数地址.然后通过函数指针调用函数, ...

  8. c++11 可变参数模板函数

    c++11 可变参数模板函数 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #in ...

  9. C++反射机制:可变参数模板实现C++反射(二)

    1. 概要   2018年Bwar发布了<C++反射机制:可变参数模板实现C++反射>,文章非常实用,Bwar也见过好几个看了那篇文章后以同样方法实现反射的项目,也见过不少从我的文章抄过去 ...

随机推荐

  1. 出现“安全时间戳无效,因为其创建时间(“2013-10-30T14:42:07.861Z”)是将来的时间。当前时间为“2013-10-30T14:36:23.988Z”,允许的时钟偏差是“00:05:00””的原因

    具体原因是服务器的时间和本地的时间不能超过5分钟,超过5分钟了.只要修改你本地机器的时间,和服务器相差的时间不能超过5分钟,就可以了. 根本原因是windows 系统域认证要求的,所有都一样.

  2. ES(4): ES Cluster Security Settings

    目录: ES安全事件回顾 ES集群安全建议 安全访问配置 license更新 ES安全事件回顾 下面是白帽汇监测到针对全球使用广泛的全文索引引擎Elasticsearch的勒索事件: 2017年1月1 ...

  3. The superclass "javax.servlet.http.HttpServlet" was not found

    在eclipse中,需要通过

  4. linux 搭建 redis

    找了很多教程总有一个适合我 http://www.cnblogs.com/_popc/p/3684835.html 当然我的目录是/opt/redis   文章中的目录是/usr/local/redi ...

  5. ghost系统下,C#获取时间带星期几的解决办法

    cmd   regedit打开注册表,进入到[HKEY_USERS\.DEFAULT\Control Panel\International]  ,然后1.将键 sDate 的值由 / 改为 - 2. ...

  6. 关于Hibernate Could not obtain transaction-synchronized Session for current thread

    转载自 http://blog.csdn.net/flyjiangs/article/details/51537381 最近几年一直再搞android,最近闲下来了,顺便玩一下web. 整了个最新版本 ...

  7. 更加灵活的编写控制层的方法____结合eval函数

    结合EVAL函数,我们可以把API放到测试用例那边去,就可以使用一个定位元素,测试用例可以使用多个API 发现eval里面可以拼接str.那么写成这样更顺眼     eval("self.d ...

  8. java实验四——测试梯形类

    package hello; public class TestTixing { public static void main(String[] args) { // TODO Auto-gener ...

  9. javascript创建对象之原型模式(三)

    少废话,先上代码: function Human() { } Human.prototype.name = "成吉思汗"; Human.prototype.sex = " ...

  10. web前端开发企业级CSS常用命名,书写规范总结

    1.常用命名 标题: title 摘要: summary 箭头: arrow 商标: label 网站标志: logo 转角/圆角: corner 横幅广告: banner 子菜单: subMenu ...