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

如何对C/C++的DECLARE_SOMETHING宏进行柯里化,实现分两步调用

实现柯里化的宏调用 CURRIED_DECLARE_SOMETHING(X)(Y)

如果要在C预处理阶段实现柯里化的宏,让CURRIED_DECLARE_SOMETHING(X)(Y)最终展开成{X, Y},可以利用宏的嵌套和临时宏定义技巧。以下是可行的实现:

// 辅助宏:负责最终生成 {X, Y}
#define _COMBINE_DECLARE(X, Y) {X, Y}

// 柯里化核心宏:第一步绑定X,返回一个能接受Y的临时宏
#define CURRIED_DECLARE_SOMETHING(X) \
    #define _CURRY_TEMP(Y) _COMBINE_DECLARE(X, Y); \
    _CURRY_TEMP

// 示例用法
struct MyStruct { int a; int b; };
struct MyStruct s1 = CURRIED_DECLARE_SOMETHING(10)(20); // 展开后等价于 {10, 20}

工作原理

  1. 当你调用CURRIED_DECLARE_SOMETHING(10)时,预处理阶段会先定义一个临时宏_CURRY_TEMP(Y),这个宏的作用是把绑定好的10和传入的Y传递给_COMBINE_DECLARE,生成{10, Y}。
  2. 紧接着返回这个临时宏_CURRY_TEMP,后面的(20)就会调用_CURRY_TEMP(20),最终展开成{10, 20}。

不过这个方案有个小限制:临时宏_CURRY_TEMP是全局的,如果在同一个作用域内连续多次调用柯里化宏,后面的定义会覆盖前面的。如果需要避免这个问题,可以用C++的lambda实现更安全的运行时柯里化:


C++ 更优雅的方案(推荐)

如果是在C++环境下,用lambda表达式实现柯里化会更简洁且无全局宏冲突问题,同样能达到声明初始化的效果:

#include <utility> // 可选,用std::pair的话需要

// 柯里化宏,返回一个lambda,接受Y后返回 {X, Y} 复合字面量或pair
#define CURRIED_DECLARE_SOMETHING(X) \
    [=](auto Y) { return std::make_pair(X, Y); } // 或者直接返回 {X, Y} 用于结构体初始化

// 示例用法
#include <iostream>
int main() {
    auto pair = CURRIED_DECLARE_SOMETHING(5)(7); // pair<int, int> 类型,值为(5,7)
    std::cout << pair.first << ", " << pair.second << std::endl;

    // 用于结构体初始化
    struct MyStruct { int a; int b; };
    MyStruct s = CURRIED_DECLARE_SOMETHING(10)(20)(); // 注意这里需要加()调用lambda,返回{10,20}
    std::cout << s.a << ", " << s.b << std::endl;
}

说明

  • lambda会捕获X的值,返回一个可调用对象,当传入Y时会生成包含X和Y的pair或结构体字面量。
  • 如果要直接初始化结构体,lambda需要返回{X,Y},此时调用时需要加()来获取初始化表达式,比如CURRIED_DECLARE_SOMETHING(10)(20)()会返回{10,20}。

解决你尝试过的 CURRY(BODY, Y) 写法问题

你之前尝试的#define CURRY(BODY, Y) BODY(Y)思路是对的,但需要先让CURRIED_DECLARE_SOMETHING(X)生成一个带Y占位符的BODY。比如可以调整为:

#define _BODY(X) (Y) {X, Y}
#define CURRY(BODY, Y) BODY(Y)
#define CURRIED_DECLARE_SOMETHING(X) _BODY(X)

// 调用方式:CURRY(CURRIED_DECLARE_SOMETHING(10), 20) → {10,20}

不过这种写法需要用CURRY来包裹两次调用,不如前面的CURRIED_DECLARE_SOMETHING(X)(Y)直观,但核心思路是通过_BODY(X)生成一个等待Y的模板,再用CURRY填充Y。

内容的提问来源于stack exchange,提问作者Lærne

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:09:04