C++ 0x 使用可变参数模板类 实现 C# 的委托机制
#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# 的委托机制的更多相关文章
- c++11 可变参数模板类
c++11 可变参数模板类 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #inc ...
- 泛化之美 —— C++11 可变参数模板的妙用
概述 首先这篇文章出自博客园作者:[qicosmos ],我对本文的实例代码进行了学习.思考和整理纠正,理清了文章的全部细节,觉得这是一篇让我受益匪浅的文章.之所以会接触「可变参数模板」这部分的内容, ...
- 第26课 可变参数模板(7)_any和variant类的实现
1. any类的实现 (1)any类: ①是一个特殊的,只能容纳一个元素的容器,它可以擦除类型,可以将何任类型的值赋值给它. ②使用时,需要根据实际类型将any对象转换为实际的对象. (2)实现any ...
- C++反射机制:可变参数模板实现C++反射(使用C++11的新特性--可变模版参数,只根据类的名字(字符串)创建类的实例。在Nebula高性能网络框架中大量应用)
1. 概要 本文描述一个通过C++可变参数模板实现C++反射机制的方法.该方法非常实用,在Nebula高性能网络框架中大量应用,实现了非常强大的动态加载动态创建功能.Nebula框架在码云的仓库地 ...
- C++反射机制:可变参数模板实现C++反射
1. 概要 本文描述一个通过C++可变参数模板实现C++反射机制的方法.该方法非常实用,在Nebula高性能网络框架中大量应用,实现了非常强大的动态加载动态创建功能.Nebula框架在Github ...
- 第27课 可变参数模板(8)_TupleHelper
1. TupleHelper的主要功能 (1)打印:由于tuple中的元素是可变参数模板,外部并不知道内部到底是什么数据,有时调试时需要知道其具体值,希望能打印出tuple中所有的元素值. (2)根据 ...
- 第24课 可变参数模板(5)_DllHelper和lambda链式调用
1. dll帮助类 (1)dll的动态链接 ①传统的调用方式:先调用LoadLibrary来加载dll,再定义函数指针类型,接着调用GetProcAddress获取函数地址.然后通过函数指针调用函数, ...
- c++11 可变参数模板函数
c++11 可变参数模板函数 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #in ...
- C++反射机制:可变参数模板实现C++反射(二)
1. 概要 2018年Bwar发布了<C++反射机制:可变参数模板实现C++反射>,文章非常实用,Bwar也见过好几个看了那篇文章后以同样方法实现反射的项目,也见过不少从我的文章抄过去 ...
随机推荐
- PHP安全之register_globals (转)
一.register_globals = Off 和 register_globals = On的区别 register_globals是php.ini里的一个配置,这个配置影响到php如何接收传递过 ...
- RedHat Enterprise Linux7.0安装Oracle12c
1. 验证 1.1 硬盘空间要求 1.1.1 安装盘 类型 占用磁盘空间 Enterprise Edition 6.4GB Standard Edition 6.1GB Standard Editio ...
- WPF Demo4
<Window x:Class="Demo4.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/ ...
- 【Spring学习笔记-4】注入集合类List、Set、Map、Pros等
概要: 当java类中含有集合属性:如List.Set.Map.Pros等时,Spring配置文件中该如何配置呢? 下面将进行讲解. 整体结构: 接口 Axe.java package org.cr ...
- php提交表单校验例子
<!DOCTYPE HTML> <meta http-equiv="Content-Type" content="text/html; charset= ...
- 1115 Counting Nodes in a BST (30 分)
1115 Counting Nodes in a BST (30 分) A Binary Search Tree (BST) is recursively defined as a binary tr ...
- js之ActiveX控件使用说明 new ActiveXObject()
什么是 ActiveX 控件? ActiveX 控件广泛用于 Internet.它们可以通过提供视频.动画内容等来增加浏览的乐趣.不过,这些程序可能出问题或者向您提供不需要的内容.在某些情况下,这些程 ...
- 第5章 进程环境(1)_进程结构(task_struct)
1. 进程的概念和进程结构 1.1 进程 (1)程序(program):是一些保存在磁盘上有序指令的集合,是存放在磁盘文件中的可执行文件.但没有任何执行的概念,它是静态的. (2)进程(process ...
- php printf() 输出格式化的字符串
php printf() 函数用于输出格式化的字符串,本文章向码农介绍php printf()函数的使用方法和基本使用实例,感兴趣的码农可以参考一下. 定义和用法 printf()函数输出格式化的字符 ...
- Solr优化案例分析
随着umc接入主机的数量越来越多,每天产生的syslog日志数量也在剧增, 之前一天产生的syslog数量才不 到1W,随着整个集团的网络设备不端接入,导致现在每天产生的syslog数量大概在180w ...