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

如何在Rust中实现类C/C++宏展开以消除冗余代码(编译时处理)

将C++编译期宏生成常量的逻辑转换为Rust实现

需求说明

现有一段C++代码,通过宏展开生成全局常量对象,希望转换为Rust实现,要求:

  • 所有处理在编译期完成,避免运行时开销
  • 无需显式声明每个常量对象,通过宏批量生成
  • 代码结构清晰,能直观看到展开后的对象属性

原C++代码

#include <iostream>
#include <string>

struct ObjAttribution {
    std::string id;
    struct attribute {
        std::string file_name;
        int code;
        std::string companion_name;
        attribute(std::string f, int c, std::string cn) : file_name(f), code(c), companion_name(cn) {}
    } attribute_type;
    ObjAttribution(std::string i, std::string f, int c, std::string cn)
    : id(i)
    , attribute_type(f, c, cn) {}
};

#define CONST_ATTRIBUTE(id, x, y, z) const ObjAttribution id(#id, #x, y, #z);
#define _x_(id, x, y, z) CONST_ATTRIBUTE(id, x, y, z)

// 生成全局常量对象
_x_(USER_IO, user_info.txt, 64, user_companion.txt)  
_x_(USER_IO_1, user_info_1.txt, 65, user_companion_1.txt)
_x_(USER_IO_2, user_info_2.txt, 66, user_companion_2.txt)
_x_(USER_IO_3, user_info_3.txt, 67, user_companion_3.txt)
_x_(USER_IO_4, user_info_4.txt, 68, user_companion_4.txt)
_x_(USER_IO_5, user_info_5.txt, 69, user_companion_5.txt)
_x_(USER_IO_6, user_info_6.txt, 70, user_companion_6.txt)
_x_(USER_IO_7, user_info_7.txt, 71, user_companion_7.txt)
_x_(USER_IO_8, user_info_8.txt, 72, user_companion_8.txt)

int main() {
    std::cout << USER_IO_1.id << " --> " << USER_IO_1.attribute_type.file_name << " --> " << USER_IO_1.attribute_type.code <<  " --> " << USER_IO_1.attribute_type.companion_name << "\n";
    std::cout << USER_IO_2.id << " --> " << USER_IO_2.attribute_type.file_name << " --> " << USER_IO_2.attribute_type.code <<  " --> " << USER_IO_2.attribute_type.companion_name << "\n";
    std::cout << USER_IO_3.id << " --> " << USER_IO_3.attribute_type.file_name << " --> " << USER_IO_3.attribute_type.code <<  " --> " << USER_IO_3.attribute_type.companion_name << "\n";
    std::cout << USER_IO_4.id << " --> " << USER_IO_4.attribute_type.file_name << " --> " << USER_IO_4.attribute_type.code <<  " --> " << USER_IO_4.attribute_type.companion_name << "\n";
    std::cout << USER_IO_5.id << " --> " << USER_IO_5.attribute_type.file_name << " --> " << USER_IO_5.attribute_type.code <<  " --> " << USER_IO_5.attribute_type.companion_name << "\n";
    std::cout << USER_IO_6.id << " --> " << USER_IO_6.attribute_type.file_name << " --> " << USER_IO_6.attribute_type.code <<  " --> " << USER_IO_6.attribute_type.companion_name << "\n";
    std::cout << USER_IO_7.id << " --> " << USER_IO_7.attribute_type.file_name << " --> " << USER_IO_7.attribute_type.code <<  " --> " << USER_IO_7.attribute_type.companion_name << "\n";

    return 0;
}

Rust实现方案

Rust中可以通过声明宏实现编译期生成全局常量,同时用&'static str保证字符串在编译期就被嵌入二进制,完全符合编译期处理的要求。

完整代码

// 定义编译期可构造的结构体,所有字段都是静态生命周期的字符串或整数
#[derive(Debug)]
struct Attribute {
    file_name: &'static str,
    code: i32,
    companion_name: &'static str,
}

#[derive(Debug)]
struct ObjAttribution {
    id: &'static str,
    attribute_type: Attribute,
}

// 声明宏:生成全局常量对象,参数对应C++宏的输入
#[macro_export]
macro_rules! const_attribute {
    ($id:ident, $file_name:literal, $code:expr, $companion_name:literal) => {
        // 生成全局常量,const保证编译期初始化
        pub const $id: ObjAttribution = ObjAttribution {
            id: stringify!($id), // 将标识符转为字符串,对应C++的#id
            attribute_type: Attribute {
                file_name: $file_name,
                code: $code,
                companion_name: $companion_name,
            },
        };
    };
}

// 简化宏调用,和原C++的_x_宏对应
#[macro_export]
macro_rules! x {
    ($id:ident, $file_name:literal, $code:expr, $companion_name:literal) => {
        const_attribute!($id, $file_name, $code, $companion_name);
    };
}

// 批量生成全局常量
x!(USER_IO, "user_info.txt", 64, "user_companion.txt");
x!(USER_IO_1, "user_info_1.txt", 65, "user_companion_1.txt");
x!(USER_IO_2, "user_info_2.txt", 66, "user_companion_2.txt");
x!(USER_IO_3, "user_info_3.txt", 67, "user_companion_3.txt");
x!(USER_IO_4, "user_info_4.txt", 68, "user_companion_4.txt");
x!(USER_IO_5, "user_info_5.txt", 69, "user_companion_5.txt");
x!(USER_IO_6, "user_info_6.txt", 70, "user_companion_6.txt");
x!(USER_IO_7, "user_info_7.txt", 71, "user_companion_7.txt");
x!(USER_IO_8, "user_info_8.txt", 72, "user_companion_8.txt");

fn main() {
    // 测试输出,格式和原C++一致
    println!(
        "{} --> {} --> {} --> {}",
        USER_IO_1.id,
        USER_IO_1.attribute_type.file_name,
        USER_IO_1.attribute_type.code,
        USER_IO_1.attribute_type.companion_name
    );
    println!(
        "{} --> {} --> {} --> {}",
        USER_IO_2.id,
        USER_IO_2.attribute_type.file_name,
        USER_IO_2.attribute_type.code,
        USER_IO_2.attribute_type.companion_name
    );
    println!(
        "{} --> {} --> {} --> {}",
        USER_IO_3.id,
        USER_IO_3.attribute_type.file_name,
        USER_IO_3.attribute_type.code,
        USER_IO_3.attribute_type.companion_name
    );
}

关键说明

  1. 编译期保证:所有常量用const关键字声明,结构体字段使用&'static str(编译期嵌入的静态字符串),确保对象在编译阶段就完成初始化,无运行时开销。
  2. 宏的作用:const_attribute!宏负责生成单个全局常量,x!宏是简化调用的包装,和原C++的宏逻辑完全对应。
  3. 结构清晰:结构体定义明确展示了对象的属性结构,宏展开后的代码可以通过cargo expand命令查看,直观验证生成的常量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 17:47:12