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

C++17中向宏传递任意带逗号模板类的技巧及默认无依赖实现

C++17中向宏传递任意带逗号模板类及默认无依赖的解决方案

一、解决宏解析含逗号模板类的核心技巧

宏会将逗号视为参数分隔符,导致带逗号的模板类(如std::map<std::string, std::vector<double>>)被错误拆分。解决方法是用括号包裹每个带逗号的类型,再通过辅助宏提取括号内的完整类型:

  • 传递参数时的写法:
    my_macro( (std::map<std::string, std::vector<double>>), double, (std::deque<std::pair<bool,double>>) )
    
  • 定义辅助宏提取类型:
    #define UNPAREN(...) __VA_ARGS__
    #define GET_TYPE(t) UNPAREN t
    
    宏内部处理参数时,用GET_TYPE(t)即可获取括号内的完整类型。

二、默认无依赖的实现方案

针对无需显式声明无依赖的需求,可通过宏的条件编译+类内类型别名实现,避免重复调用wrapper_no_dependencies:

方案1:包装类模板带默认空tuple参数

将包装类设计为模板,默认依赖类型设为std::tuple<>,无依赖时无需额外声明:

#include <tuple>
#include <utility>

template<typename T, typename Dependencies = std::tuple<>>
class Wrapper {
public:
    using dependencies__ = Dependencies;

    static void expose() {
        // 暴露当前类成员的逻辑
        // ...
        // 遍历依赖调用expose
        std::apply([](auto&&... args) {
            (decltype(args)::expose(), ...);
        }, dependencies__{});
    }
};

配合宏声明具体类的包装:

#define wrapper_declare(CLASS_TYPE, ...) \
template<typename... Args> \
class Wrapper<CLASS_TYPE<Args...>> : public BaseWrapper { \
    using dependencies__ = std::tuple<GET_TYPE(__VA_ARGS__)...>; \
    // 构造函数、成员声明等逻辑 \
};

// 无依赖调用:wrapper_declare(Hello)
// 有依赖调用:wrapper_declare(Hello, (Wrapper<Foo>), (Wrapper<Bar<int>>))

方案2:C++17兼容的宏条件判断

利用宏的可变参数特性,定义自动判断是否为空的宏,为空时默认生成空tuple:

// 辅助宏:处理依赖类型
#define DEPENDENCY_TYPE(...) \
    DEPENDENCY_TYPE_IMPL(__VA_ARGS__, std::tuple<GET_TYPE(__VA_ARGS__)...>, std::tuple<>)

#define DEPENDENCY_TYPE_IMPL(a, b, c, ...) b

// 包装类声明宏
#define wrapper_declare(CLASS_TYPE, ...) \
class Wrapper_##CLASS_TYPE : public BaseWrapper { \
public: \
    DEPENDENCY_TYPE(__VA_ARGS__) \
    \
    static void expose() { \
        // 当前类暴露逻辑 \
        std::apply([](auto&&... dep_wrappers) { \
            (decltype(dep_wrappers)::expose(), ...); \
        }, dependencies__{}); \
    } \
    // 构造函数等其他声明 \
};

当调用wrapper_declare(Hello)时,DEPENDENCY_TYPE会生成std::tuple<>;传递依赖时则生成包含指定类型的tuple。

三、完整代码示例

#include <tuple>
#include <iostream>
#include <string>
#include <vector>

// 辅助宏:去掉括号提取类型
#define UNPAREN(...) __VA_ARGS__
#define GET_TYPE(t) UNPAREN t

// 依赖类型处理宏
#define DEPENDENCY_TYPE(...) \
    DEPENDENCY_TYPE_IMPL(__VA_ARGS__, std::tuple<GET_TYPE(__VA_ARGS__)...>, std::tuple<>)

#define DEPENDENCY_TYPE_IMPL(a, b, c, ...) b

// 基础包装类
class BaseWrapper {
public:
    virtual ~BaseWrapper() = default;
    virtual void expose() = 0;
};

// 通用包装类模板
template<typename T>
class Wrapper : public BaseWrapper {
public:
    using dependencies__ = std::tuple<>;

    void expose() override {
        std::cout << "Exposing generic type: " << typeid(T).name() << "\n";
        std::apply([](auto&&...) {}, dependencies__{});
    }
};

// 自定义类声明宏
#define wrapper_declare(CLASS_TYPE, ...) \
template<typename... Args> \
class Wrapper<CLASS_TYPE<Args...>> : public BaseWrapper { \
public: \
    DEPENDENCY_TYPE(__VA_ARGS__) \
    \
    void expose() override { \
        std::cout << "Exposing " << typeid(CLASS_TYPE<Args...>).name() << "\n"; \
        std::apply([](auto&&... deps) { \
            (decltype(deps)::expose(), ...); \
        }, dependencies__{}); \
    } \
};

// 示例模板类
template<typename T>
class Foo {};

template<typename T, typename U>
class Bar {};

// 无依赖包装声明
wrapper_declare(Foo)

// 带依赖包装声明
wrapper_declare(Bar, (Wrapper<Foo<int>>), (Wrapper<std::vector<std::string>>))

int main() {
    Wrapper<Bar<double, float>> bar_wrapper;
    bar_wrapper.expose();
    return 0;
}

内容的提问来源于stack exchange,提问作者Caduchon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 08:02:52