C++用模版封装一个万能函数

使用场景

有时候我们需要访问一些数据,并对数据进行一些操作,例如遍历一棵树,并对树的节点做一些操作。我们可以写一些DFS或者BFS遍历函数,并访问每一个节点做出相应动作, 如果我们有很多种操作行为,那么我们就需要写很多种这种遍历函数,聪明的你,可能已经想到,我可以将操作当做一个回调函数传入到遍历函数里面,这样就可以复用遍历代码。

对于单一的操作行为,这种方式是有效的,但是如果有很多种不同的操作行为,显然事先定义好的回调函数,可能不够用了。对于这种需求场景,我们可以使用访问者设计模式(Visit模式),该设计模式是典型的将数据和数据的操作分离的方法。不过,这里我并不想介绍访问者模式,而是介绍怎么用模版实现一个具有弹性的"回调函数",可以包装任意返回值,任意函数体,任意参数的可调用对象。

代码实现

闲话不说,直接看代码,核心是利用function和可变参数模版。

cpp 复制代码
#include <iostream>
#include <functional>

template<typename RetType>
class UniversalWrapper {
public:
	// 构造函数,接受一个函数和任意
	template<typename Func, typename... Args>
	UniversalWrapper(Func&& func, Args&&... args)
		: func_(std::bind(std::forward<Func>(func), std::forward<Args>(args)...)) {}

	// 仿函数
	RetType operator()() {
		return func_();
	}

private:
	std::function<RetType( )> func_;
};

int add(int a, int b) {
	return a + b;
}

std::string greet(const std::string& name, const std::string& greeting = "Hello") {
	return greeting + ", " + name + "!";
}

int main() {
	
	UniversalWrapper<int> wrapper1(add, 3, 5);  
	UniversalWrapper<std::string> wrapper2(greet, "Alice", "Hi"); 

	auto result1 = wrapper1();  
	auto result2 = wrapper2(); 

	std::cout << "Result1: " << result1 << std::endl; 
	std::cout << "Result2: " << result2 << std::endl; 

	return 0;
}

总结

这个实现通过模板参数 RetType 指定了返回值类型,并使用 std::function<RetType()> 存储绑定后的函数。你能够灵活地传递不同的函数和参数,并使用仿函数的形式调用它们。 这里你也可以把operator()设计成带参数的函数,只要在bind的时候留好place_holder就可以了。

相关推荐
学逆向的5 分钟前
C 突破编译器限制
c语言·开发语言·网络安全
碧海银沙音频科技研究院5 分钟前
基于炬芯ATS录音卡BLE控制协议
人工智能·嵌入式硬件·算法·语音识别
jimy122 分钟前
C++ 虚函数表:基类和派生类共用一张 vtable 吗?
开发语言·c++
爱吃提升30 分钟前
Dev-C++ 5.11 C++断点调试完整教程
开发语言·c++
夜晚回家36 分钟前
Python 原始字符串详解 | r 前缀到底让什么不再转义
开发语言·python
suhan40 分钟前
【数据结构】三、栈和队列:6.链队列、双端队列、队列的应用(树的层次遍历、广度优先BFS、先来先服务FCFS)
数据结构·后端·算法
陈年老古董42 分钟前
PyQt5 入门指南:环境搭建、PyCharm 外部工具配置与登录界面实战
开发语言·qt·pycharm
姜鱼问生1 小时前
Docker Volume 备份与恢复实战:不停机迁移数据
后端·算法·架构
suhan1 小时前
【数据结构】三、栈和队列:5.顺序队列(循环队列)(初始化,判空判满,入队,出队,实例)
数据结构·后端·算法
看浪的路人1 小时前
第7讲:大模型后端服务化——Go 实现高并发 LLM Proxy / Router / Fallback
开发语言·后端·golang