C++17中是否有替代#define实现类似Python partial的参数绑定方法?
问题描述
现有如下C++代码:
#include <iostream> #include <string> using namespace std; template<typename... Ts> void logger(const string& who, const string& where, Ts... args) { cout << "This is " << who << " in " << where << endl; // 伪代码,实际需用折叠表达式处理参数输出 (cout << ... << args) << endl; } class Base { protected: string who = "Base"; public: Base() {} Base(const string& who):who(who){} public: template<typename... Ts> void func_Base(Ts... args) { logger(who, __FUNCTION__, args...); } }; class A:public Base { public: A() : Base("A") {}; public: template<typename... Ts> void func_A(Ts... args) { logger(who, __FUNCTION__, args...); } }; class B :public Base { public: B() : Base("B") {}; public: template<typename... Ts> void func_B(Ts... args) { logger(who, __FUNCTION__, args...); } };
需求是:在派生类的函数中调用logger时,自动输出当前类指定的who字符串和函数名__FUNCTION__,无需手动传入这两个参数,就像使用宏#define logger(args...) logger(who, __FUNCTION__, args...)那样,仅通过logger(args...)完成调用。询问是否存在C++17的方法替代该宏实现此功能。
C++17 解决方案
可以通过在基类中封装成员模板函数的方式替代宏,既保证类型安全,又能实现自动传递参数的效果,具体实现如下:
- 将原有全局
logger移入细节命名空间,避免命名冲突; - 在
Base类中定义成员模板函数logger,自动捕获当前类的who成员和当前函数名__FUNCTION__,调用底层日志函数; - 派生类继承
Base后,直接调用成员函数logger(args...)即可。
修改后的代码示例:
#include <iostream> #include <string> // 细节命名空间,存放底层日志实现 namespace detail { template<typename... Ts> void logger(const std::string& who, const std::string& where, Ts... args) { std::cout << "This is " << who << " in " << where << std::endl; // C++17折叠表达式处理可变参数输出 ((std::cout << args << " "), ...) << std::endl; } } class Base { protected: std::string who = "Base"; public: Base() {} Base(const std::string& who): who(who) {} // 封装后的成员日志函数,自动传递who和当前函数名 template<typename... Ts> void logger(Ts... args) { detail::logger(who, __FUNCTION__, args...); } }; class A : public Base { public: A() : Base("A") {}; template<typename... Ts> void func_A(Ts... args) { // 直接调用,无需手动传who和__FUNCTION__ logger(args...); } }; class B : public Base { public: B() : Base("B") {}; template<typename... Ts> void func_B(Ts... args) { logger(args...); } }; // 测试示例 int main() { A a; a.func_A("Hello", 123, true); B b; b.func_B("World", 45.6); Base base; base.logger("Test base"); return 0; }
方案说明
- 利用C++17的可变参数模板和折叠表达式处理参数输出,保证类型安全;
- 基类成员
logger自动获取当前类的who成员,以及通过__FUNCTION__获取调用函数名,无需手动传入; - 相比宏方案,避免了预处理器的潜在问题(如参数展开陷阱、命名污染),同时保留代码可读性与可维护性;
- 派生类继承
Base后自然拥有该成员函数,调用方式完全符合需求。
内容的提问来源于stack exchange,提问作者f1msch
相关产品推荐
相关产品推荐

