You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 解决方案

可以通过在基类中封装成员模板函数的方式替代宏,既保证类型安全,又能实现自动传递参数的效果,具体实现如下:

  1. 将原有全局logger移入细节命名空间,避免命名冲突;
  2. 在Base类中定义成员模板函数logger,自动捕获当前类的who成员和当前函数名__FUNCTION__,调用底层日志函数;
  3. 派生类继承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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 02:23:24