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

是否存在无需使用宏即可实现token pasting(令牌粘贴)的技术方案?

C++ 无需宏实现重复代码模式的替代方案

你当前遇到的是典型的「变量名+枚举名同步匹配」的重复代码场景,原来的实现依赖C宏的##token拼接能力,现在C++标准已经有无需宏的替代实现方案:


你需要复用的核心逻辑为:

// Token替换为实际变量名
if (Token != PreviousToken)
{
    SomeFunc(SomeEnum::Token,Token);
    PreviousToken = Token;
}

方案1:C++20 模板+编译期字符串匹配(完全无宏)

C++20开始支持把字符串字面量作为模板参数,配合编译期常量判断可以实现和宏完全一致的编译期展开效果,同时自带类型检查,不会出现宏的符号优先级、作用域污染等问题:

#include <string_view>

// 通用更新模板
template<std::string_view VarName, typename T>
void UpdateIfChanged(T& current, T& prev)
{
    if (current != prev)
    {
        // 编译期匹配对应枚举值,无运行时开销
        if constexpr (VarName == "Token1") SomeFunc(SomeEnum::Token1, current);
        else if constexpr (VarName == "Token2") SomeFunc(SomeEnum::Token2, current);
        // 剩余20+变量依次添加对应匹配分支即可
        prev = current;
    }
}

调用方式:

UpdateIfChanged<"Token1">(Token1, PreviousToken1);
UpdateIfChanged<"Token2">(Token2, PreviousToken2);

方案2:C++26 静态反射(最优解,无需手动写匹配分支)

C++26已经正式纳入静态反射特性,后续可以直接通过编译期反射自动获取变量名、匹配对应枚举值,连上面的编译期分支都不需要手动编写:

#include <reflect> // C++26标准反射库

template<typename T>
void UpdateIfChanged(T& current, T& prev)
{
    if (current != prev)
    {
        // 编译期自动获取变量名、匹配对应枚举值
        constexpr auto var_name = std::reflect::name_of_v<current>;
        constexpr auto enum_val = std::reflect::enum_from_name_v<SomeEnum, var_name>;
        SomeFunc(enum_val, current);
        prev = current;
    }
}

调用方式更简洁:

UpdateIfChanged(Token1, PreviousToken1);
UpdateIfChanged(Token2, PreviousToken2);

低版本编译环境过渡方案

如果当前编译环境不支持C++20,依然优先推荐用宏实现,对比手动写20+份重复代码,宏的维护成本更低,只要做好参数防护即可避免大部分问题:

// 加do while(0)、参数加括号避免宏展开错误
#define UPDATE_IF_CHANGED(Token) \
do { \
    if ((Token) != Previous##Token) { \
        SomeFunc(SomeEnum::##Token, (Token)); \
        Previous##Token = (Token); \
    } \
} while(0)

调用方式:UPDATE_IF_CHANGED(Token1);

内容的提问来源于stack exchange,提问作者Eyal K.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 11:18:04