`

C++11应用:占位模式

 
阅读更多

    有人称为命令模式,好比先定义了一个命令(行为+参数),然后把这个命令,加入到排队、传递等策略中,等到合适的时机再操作执行。而我觉得更像机器学习中的placeholder占位模式,把函数的地址和传入参数都绑定了,再手动操作执行:

#include <functional>
#include <type_traits>

template <typename R=void>
struct CommCommand
{
private:
	std::function<R()> m_f;
public:

	// 接受可以调用对象的函数封包器
	template <class F, class... Args, class=typename std::enable_if<!std::is_member_function_pointer<F>::value>::type>
	void Wrap(F&& f, Args&&... args)
	{
		m_f = [&] {return f(args...); };
	}

	// 接受常量成员函数的封包器
	template <class R, class C, class... DArgs, class P, class... Args>
	void Wrap(R(C::*f)(DArgs...) const, P&& p, Args&&... args)
	{
		m_f = [&, f] {return (*p.*f)(args...); };
	}

	// 接受非常量成员函数的函数包装器
	template <class R, class C, class... DArgs, class P, class... Args>
	void Wrap(R(C::*f)(DArgs...), P&& p, Args&&... args)
	{
		m_f = [&, f] {return (*p.*f)(args...); };
	}

	R Execute() 
	{
		return m_f();
	}
};

struct STA
{
	int m_a;
	int operator()()
	{
		return m_a;
	}
	int operator()(int n)
	{
		return m_a + n;
	}
	int triple0() 
	{
		return m_a * 3;
	}
	int triple(int a)
	{
		return m_a * 3 + a;
	}
	int triple1() const
	{
		return m_a * 3;
	}
	const int triple2(int a) const
	{
		return m_a * 3 + a;
	}
	void triple3()
	{
		cout << "triple3" << endl;
	}
	
};
int add_one(int n)
{
	cout << "add_one" << endl;
	return n + 1;
}
void printTest()
{
	cout << "printTest" << endl;
}

void test()
{
	CommCommand<int> cmd;
	// 普通函数
	cmd.Wrap(add_one, 0);
	// lambda表达式
	cmd.Wrap([](int n) {return n + 1; }, 2);
	// 接受函数对象
	typedef int(*Fun)(int);
	Fun f = add_one;
	cmd.Wrap(f, 5);

	STA t = { 10 };
	int x = 3;
	// 接受成员函数
	cmd.Wrap(&STA::triple0, &t);
	cmd.Wrap(&STA::triple, &t, x);
	cmd.Wrap(&STA::triple, &t, 3);
	cmd.Wrap(&STA::triple2, &t, x);
	
	auto r = cmd.Execute();

	cout << "result:" << r << endl;

	CommCommand<void> cmd1;
	cmd1.Wrap(&STA::triple3, &t);
        cmd1.Wrap(printTest);
	cmd1.Execute();
}
int main(int, char *[])
{     
	test();  
	 
	system("pause");
	return 0;
}

 

   另外一种实现:

template <typename Receiver>
class Command 
{

public:
	typedef void(Receiver::*Action)();
	Command(Receiver* r, Action a):_receiver(r), _action(a) {}
	virtual void Execute();
protected:
	Action _action;
	Receiver* _receiver;
};

template <typename Receiver> 
void Command<Receiver>::Execute() // 等同实现SimpleCommand子类
{
	(_receiver->*_action)(); // 可以使用Command中private变量
}

template <typename Receiver>
class SimpleCommand :Command<Receiver>
{
public:  
	SimpleCommand(Receiver* r, Action a) :Command<Receiver>(r, a) {} 

	void Execute() {
		(_receiver->*_action)();  // 不能使用Command中private变量
	}
};


class MyClass
{
public:
	void print()
	{
		cout << "MyClass print..." << endl;
	}
};

void test() { 
	MyClass* receiver = new MyClass;

	Command<MyClass>* cmd = new Command<MyClass>(receiver, &MyClass::print);
	cmd->Execute();

	SimpleCommand<MyClass>* simpleCommand = new SimpleCommand<MyClass>(receiver, &MyClass::print);
	simpleCommand->Execute();
 
}
 

 

 

分享到:
评论

相关推荐

    设计模式C++学习之代理模式(Proxy)

    代理模式的应用非常广泛,例如在图像处理、数据缓存、权限控制等场景。通过代理模式,我们可以灵活地在不修改原有代码的基础上增强功能或控制访问,提高了代码的可维护性和可扩展性。在C++中,合理利用代理模式能够...

    c++设计模式精解-GoF 23种设计模式解析附C++实现源码

    ### c++设计模式精解—GoF 23种设计模式解析附C++实现源码 #### 0. 引言 设计模式是面向对象编程领域的重要组成部分,它提供了一系列解决常见问题的方法论。本文旨在深入解析GoF(Gang of Four)所提出的23种设计...

    C++封装版sqlite3

    为了方便C++开发,我们可以对sqlite3进行封装,以更好地融入C++的编程模式。本文将详细探讨如何将C版sqlite3封装为C++版,并介绍其中的关键特性,如动态参数绑定、查询辅助类、表字段操作以及异常处理和事务管理。 ...

    c++代码生成器

    4. **跨平台**:Python可以在多个操作系统上运行,这意味着生成的C++代码生成器也可应用于多种环境。 【Python实现C++代码生成器】 使用Python编写C++代码生成器通常包括以下几个步骤: 1. **定义模板**:定义C++...

    C++设计模式代码资源15_Proxy.zip

    在软件工程领域,设计模式是一种在特定情境下解决常见问题的经验总结,被广泛应用于各种编程语言,包括C++。Proxy(代理)设计模式是其中的一种,它为其他对象提供一个替代品或代表,以控制对这个对象的访问。在本...

    C++设计模式

    根据给定文件的信息,本文将深入探讨C++设计模式的核心概念与应用实例。设计模式作为软件工程中的重要组成部分,能够帮助开发人员解决常见的设计问题,提高代码复用性、灵活性和扩展性。以下是对每种设计模式的具体...

    设计模式精解 模式 解析

    - **2.7 Proxy模式**:代理模式为另一个对象提供一个代理或占位符以控制对这个对象的访问。代理对象可以在客户端和目标对象之间起到中介的作用,并且可以通过代理对象去除、添加或扩展功能。 #### 3. 行为模式 ...

    Visual C++经典画图程序

    在项目压缩包中的"od"可能是指一个遗漏的文件名或者一个占位符,通常一个完整的Visual C++画图程序项目会包含源代码文件(.cpp和.h)、资源文件(.rc)、工程文件(.vcxproj)以及可能的其他辅助文件,如图片资源等...

    c++ ado

    以上就是C++ ADO编程中的主要知识点,通过这些内容,我们可以构建和操作数据库应用程序。在实践中,还需要熟悉数据库管理系统(如SQL Server、Oracle等)的相关知识,以及对ODBC和OLE DB的理解,以便更好地利用ADO...

    Cross-platform modern c++ GUI.zip

    现代C++通常指的是C++11及以后的版本,这些版本引入了诸多改进,包括更好的内存管理、更安全的特性以及对并发编程的支持。 在跨平台GUI开发中,开发者通常会利用库或框架来简化工作,如Qt、wxWidgets、GTK+、FLTK等...

    Turbo C++.zip

    1. **C编程软件**:C语言是一种基础且强大的编程语言,被广泛应用于系统开发、软件构建、游戏编程等多个领域。Turbo C++提供了一个完整的环境,包括源代码编辑器、编译器、链接器和调试器,使得C程序的编写和测试变...

    C++ 6.0 Template(模板库)参考手册.zip

    1. 类型参数(Type Parameter):如前面提到的`T`,用于表示可以替换为任何类型的占位符。 2. 非类型参数(Non-Type Parameter):可以是整型、指针或枚举类型,它们在模板实例化时必须提供具体的值。 三、模板特化...

    C++完整数据库SQLServer操作类(ODBC)

    在IT行业中,数据库操作是应用程序开发中的重要环节,尤其是在企业级应用中。C++作为一款强大的编程语言,虽然原生不支持内置的数据库接口,但可以通过ODBC(Open Database Connectivity)来实现对多种数据库系统的...

    SQlite3高级应用篇(C/C++编程接口) 源代码

    SQLite3是一种轻量级、开源的嵌入式数据库引擎,广泛应用于各种软件开发中,尤其在C和C++编程环境中。本高级应用篇主要探讨如何利用C/C++编程接口与SQLite3进行深度交互,实现更高效、灵活的数据管理。下面我们将...

    C++基于线程池技术实现大并发网络IO框架,一个基于C++11的轻量级网络框架

    网络库 tcp/udp客户端,接口简单易用并且是线程安全的,用户不必关心具体的socket api操作。 tcp/udp服务器,使用非常简单,只要实现具体的tcp/udp会话(Session类)...命令行解析工具,可以很便捷的实现可配置应用程序

    设计模式_代理模式

    代理模式的主要目的是为其他对象提供一个替代品或占位符,以便控制对原对象的访问。这种模式允许我们创建一个代理类,该类代表一个真实对象,并在客户和真实对象之间起到中介的作用。这样可以实现很多功能,比如增加...

    Absolute C++中文版(原书第2版)-完美的C++教程,文档中还包含英文版

    全书围绕c++语言的结构来组织,开始章节介绍编程的普通概念,接下来详细介绍C++hh的继承、多态、异常处理以及标准模板库(STL),同时还包含模式和uML的介绍。本书内容系统、全面,给出了大量代码示例、自测练习、编程...

    more effective c++

    #### Item 11:禁止异常信息(EXCEPTIONS)传递到析构函数外 - **目的**:确保析构函数能够正常执行,避免析构过程中抛出异常。 - **实现**:通过异常安全的设计,确保即使出现异常,析构函数也能正常工作。 #### ...

    Hough变换C++程序

    Hough变换是一种在图像处理领域广泛使用的算法,主要用于检测图像中的几何形状,如直线...通过理解和应用这个程序,开发者可以深入学习图像处理和计算机视觉的基本技术,为进一步的图像分析和模式识别打下坚实的基础。

Global site tag (gtag.js) - Google Analytics