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

C++可变参数宏拼接生成变量名及编译期constexpr实现方法

可变参数宏实现方案

预处理器本身没有原生的递归拼接可变参数的能力,需要借助参数计数+分支展开的辅助宏实现。另外你需求中调用时参数带引号的形式无法直接生成合法变量名,因为引号会被识别为预处理器标记的一部分,无法自动剥离,因此我们调整为参数传无引号的标记,宏内部自动处理标识符拼接和字符串加引号逻辑,完全符合你要求的生成结果:

// 手动实现基础辅助宏,无需引入第三方依赖
#define PP_NARG(...) \
         PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) \
         PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
          _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
         _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
         _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
         _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
         _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
         _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
         _61,_62,_63,N,...) N
#define PP_RSEQ_N() \
         63,62,61,60,                   \
         59,58,57,56,55,54,53,52,51,50, \
         49,48,47,46,45,44,43,42,41,40, \
         39,38,37,36,35,34,33,32,31,30, \
         29,28,27,26,25,24,23,22,21,20, \
         19,18,17,16,15,14,13,12,11,10, \
         9,8,7,6,5,4,3,2,1,0

// 可按需扩展到更多参数,这里以3参数为例匹配你的示例
#define JOIN_IDENT_1(delim, a) a
#define JOIN_IDENT_2(delim, a, b) a##delim##b
#define JOIN_IDENT_3(delim, a, b, c) a##delim##b##delim##c

#define JOIN_STR_1(delim, a) #a
#define JOIN_STR_2(delim, a, b) #a #delim #b
#define JOIN_STR_3(delim, a, b, c) #a #delim #b #delim #c

#define JOIN_IDENT(N, delim, ...) JOIN_IDENT_##N(delim, __VA_ARGS__)
#define JOIN_STR(N, delim, ...) JOIN_STR_##N(delim, __VA_ARGS__)

#define def_name(delim, ...) \
inline constexpr char const JOIN_IDENT(PP_NARG(__VA_ARGS__), delim, __VA_ARGS__)##_name[] { JOIN_STR(PP_NARG(__VA_ARGS__), delim, __VA_ARGS__) };

使用示例

调用写法和生成结果完全匹配你的要求:

// 下划线分隔场景
def_name(_, abc, def, ghi);
// 展开后生成:inline constexpr char const abc_def_ghi_name[]{"abc_def_ghi"};

// 无分隔符场景
def_name(, abc, def, ghi);
// 展开后生成:inline constexpr char const abcdefghi_name[]{"abcdefghi"};

宏实现限制

  • 最多支持的参数个数由你扩展的JOIN_IDENT_xx/JOIN_STR_xx最大序号决定,上述示例默认支持最多3个参数,可自行扩展到需要的数量
  • 参数只能是合法的C++标识符字符,不能包含空格、特殊符号

C++ constexpr实现方案

首先明确:变量名属于C++语法层面的标识符,只能由预处理器生成,模板和constexpr只能操作编译期值,无法生成新的标识符。如果你不需要自动生成变量名,只需要编译期生成拼接后的字符串常量,可以用纯constexpr实现,不需要依赖预处理器:

#include <string_view>
#include <array>
#include <algorithm>

// C++20及以上版本实现
template<typename... Args>
constexpr auto join_str(std::string_view delim, Args... parts) 
requires (std::is_convertible_v<Args, std::string_view> && ...) {
    constexpr size_t N = sizeof...(parts);
    std::array<std::string_view, N> part_arr{static_cast<std::string_view>(parts)...};
    
    size_t total_size = 0;
    for (auto p : part_arr) total_size += p.size();
    total_size += delim.size() * (N > 0 ? N - 1 : 0);

    std::array<char, total_size + 1> res{};
    char* ptr = res.data();
    for (size_t i = 0; i < N; ++i) {
        if (i > 0) {
            std::copy_n(delim.data(), delim.size(), ptr);
            ptr += delim.size();
        }
        std::copy_n(part_arr[i].data(), part_arr[i].size(), ptr);
        ptr += part_arr[i].size();
    }
    *ptr = '\0';
    return res;
}

使用示例

constexpr auto abc_def_ghi_name = join_str("_", "abc", "def", "ghi");
constexpr auto abcdefghi_name = join_str("", "abc", "def", "ghi");

该实现的优点是不需要预处理器,支持任意数量的参数,参数可以是任意编译期字符串,不需要符合标识符规则。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 02:36:04