C++20中如何让代理类自动调用对应原始类的同名同参函数?
在C++20中简化代理类的自动调用实现
问题场景
我有一个原始类Original和代理类Proxy,代理类的每个成员函数需要添加日志、条件检查等额外逻辑,同时调用原始类的同名同参函数。当前实现需要手动传入原始类的函数指针和参数,希望在C++20中实现仅调用call()就能自动完成对应原始函数的调用,无需手动指定函数名和参数。
当前代码实现:
class Original { public: void function1(int a) { // Implementation of function1 } int function2(double b) { // Implementation of function2 } // More functions... }; class Proxy { private: Original original; public: template <typename Func, typename... Args> auto call(Func func, Args&&... args) -> decltype((original.*func)(std::forward<Args>(args)...)) { return (original.*func)(std::forward<Args>(args)...); } void function1(int a) { //Do some condition check and logging call(&Original::function1, a); //Do some condition check and logging } void function2(double b) { //Do some condition check and logging call(&Original::function2, b); //Do some condition check and logging } // More functions... };
解决方案
C++20尚未支持完整的编译时反射,无法实现完全无需指定函数名的call()调用,但可以通过宏封装或模板辅助大幅简化代码,避免重复编写函数指针和参数传递逻辑。
方案一:宏封装自动生成代理函数
通过宏批量生成代理类成员函数,自动完成日志逻辑和原始函数调用,仅需一行宏调用即可完成:
#include <functional> // 用于std::invoke class Original { public: void function1(int a) { // 原始函数实现 } int function2(double b) { // 原始函数实现 return static_cast<int>(b * 2); } // 更多函数... }; class Proxy { private: Original original; // 通用call方法,封装原始函数调用逻辑 template <auto Func, typename... Args> decltype(auto) call(Args&&... args) { return std::invoke(Func, original, std::forward<Args>(args)...); } public: // 定义宏:自动生成带日志逻辑的代理函数 #define DEFINE_PROXY_FUNC(ret_type, func_name, ...) \ ret_type func_name(__VA_ARGS__) { \ // 前置日志/条件检查逻辑 \ call<&Original::func_name>(__VA_ARGS__); \ // 后置日志/条件检查逻辑 \ } // 生成代理函数 DEFINE_PROXY_FUNC(void, function1, int a) DEFINE_PROXY_FUNC(int, function2, double b) // 取消宏定义,避免污染全局命名空间 #undef DEFINE_PROXY_FUNC // 更多函数... };
方案二:C++20模板与自动参数推导
如果不想使用宏,可以借助C++20模板特性简化参数传递,仅需指定一次原始函数指针:
#include <functional> class Original { public: void function1(int a) { /* ... */ } int function2(double b) { /* ... */ return 0; } }; class Proxy { private: Original original; // 模板化call方法,自动推导参数类型 template <auto Func, typename... Args> decltype(auto) call(Args&&... args) { return std::invoke(Func, original, std::forward<Args>(args)...); } public: void function1(int a) { // 前置日志/检查逻辑 call<&Original::function1>(a); // 后置日志/检查逻辑 } int function2(double b) { // 前置日志/检查逻辑 auto result = call<&Original::function2>(b); // 后置日志/检查逻辑 return result; } };
说明
- 宏封装方案是当前最简洁的实现方式,彻底避免了重复编写函数指针和参数的冗余代码。
- 模板方案保留了手动指定函数指针的步骤,但通过
std::invoke统一了成员函数调用逻辑,简化了参数传递写法。 - 完整的编译时反射支持需等待C23及后续标准的进一步完善,当前C20无法实现完全无参数的
call()自动匹配。
内容的提问来源于stack exchange,提问作者suresh kumar
相关产品推荐
相关产品推荐

