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

如何在C++中不使用#define宏实现const char*编译期拼接?

解决方案:编译期const char*拼接(无#define依赖)

针对你的需求,在C++20(GCC 12.1.1完全支持)环境下,你可以通过constexpr模板元编程或者编译期字符串容器实现无#define的字符串拼接,以下是两种可靠方案:

方案1:constexpr模板拼接函数

利用C++20的constexpr特性,编写模板函数在编译期计算拼接后的字符串长度并生成新的const char*:

#include <cstddef>
#include <utility>

// 编译期获取字符串长度
constexpr std::size_t cstr_len(const char* s) {
    std::size_t len = 0;
    while (s[len] != '\0') ++len;
    return len;
}

// 编译期拼接两个const char*的实现细节
template<std::size_t N1, std::size_t N2, std::size_t... Is1, std::size_t... Is2>
constexpr const char* concat_impl(const char* s1, const char* s2, 
                                  std::index_sequence<Is1...>, std::index_sequence<Is2...>) {
    static const char result[N1 + N2] = {s1[Is1]..., s2[Is2]..., '\0'};
    return result;
}

// 对外暴露的拼接接口
template<const char* S1, const char* S2>
constexpr const char* concat() {
    constexpr std::size_t len1 = cstr_len(S1);
    constexpr std::size_t len2 = cstr_len(S2);
    return concat_impl<len1, len2>(S1, S2, 
                                   std::make_index_sequence<len1>{}, 
                                   std::make_index_sequence<len2>{});
}

使用示例

constexpr const char* productName = "CloysterHPC";
constexpr const char* installerSuffix = " Installer";

class Newt : public View {
private:
    struct TUIText {
        static constexpr const char* title = concat<productName, installerSuffix>();
    };
};

该方案完全在编译期执行,生成的title是指向静态const字符数组的constexpr指针,效果和#define拼接一致且无宏依赖。

方案2:利用C++20 constexpr std::string(修正误解)

你之前对std::string的constexpr特性存在误解:C++20的std::string确实支持编译期操作,但不能直接将.data()结果作为constexpr const char*存储(编译期std::string的内存不满足静态存储期要求)。但可以通过将内容复制到静态数组实现:

#include <string>
#include <array>

template<const char* S1, const char* S2>
constexpr const char* concat_str() {
    constexpr std::string s = std::string(S1) + S2;
    static constexpr std::array<char, s.size() + 1> arr = [](){
        std::array<char, s.size() + 1> a{};
        for (std::size_t i = 0; i < s.size(); ++i) {
            a[i] = s[i];
        }
        a[s.size()] = '\0';
        return a;
    }();
    return arr.data();
}

使用示例

constexpr const char* productName = "CloysterHPC";

class Newt : public View {
private:
    struct TUIText {
        static constexpr const char* title = concat_str<productName, " Installer">();
    };
};

该方案借助C++20 constexpr std::string的拼接能力,将结果存入静态constexpr数组,确保指针生命周期覆盖整个程序运行期。

纠正你的关键误解

  • fmt::format的constexpr支持:fmt库从9.0版本才开始支持constexpr格式化,GCC 12.1.1默认配套的fmt版本可能较低;且即使支持,编译期格式化结果也无法直接转为静态const char*(和std::string同理)。
  • __cpp_lib_constexpr_string的用途:该宏标记的是std::string的constexpr操作支持(如构造、拼接),不代表可以直接将其内部指针作为静态constexpr使用。
  • C++20文本处理限制:C++20允许编译期字符串操作,但静态存储期的const char*必须指向静态数组,不能直接引用编译期临时对象的内存。

内容的提问来源于stack exchange,提问作者Vinícius Ferrão

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 05:30:52