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

如何在保持API简洁的前提下拼接编译期类字符串对象?

编译期拼接类字符串对象的扩展需求

我尝试在编译期拼接类字符串对象,实现了如下代码,但该实现仅支持字符串字面量和char数组,希望能扩展功能以支持其他编译期类字符串对象:

#include <cstddef>
#include <utility>
#include <algorithm>
#include <array>
#include <string_view>

template <std::size_t N>
class CharArray
{
  private:
    std::array<char, N> _string;

    template <std::size_t S>
    friend class CharArray;

    template <std::size_t S1, std::size_t S2>
    constexpr CharArray(const std::array<char, S1> s1, const std::array<char, S2> s2)
        : _string() {
        std::copy(s1.begin(), s1.end() - 1, _string.begin());
        std::copy(s2.begin(), s2.end() - 1, _string.begin() + S1 - 1);
    }

  public:
    constexpr CharArray(const char (&str)[N]) : _string() {
        std::copy(&str[0], &str[0] + N, _string.begin());
    }

    constexpr CharArray(const std::array<char, N>& str) : _string() {
        std::copy(std::cbegin(str), std::cend(str), _string.begin());
    }

    template <std::size_t S>
    constexpr auto operator+(const CharArray<S> other) const {
        return CharArray<N + other._string.size() - 1>(_string, other._string);
    }

    [[nodiscard]]
    constexpr auto c_str() const {
        return _string.data();
    }
};

template <std::size_t N, typename... Strings>
constexpr auto join_chars(const char (&first)[N], Strings&&... rest) {
    if constexpr (!sizeof...(Strings)) { return CharArray<N>{first}; }
    else {
        return CharArray<N>{first} + join_chars(std::forward<Strings>(rest)...);
    }
}

#include <iostream>

int main() {
    // 这段代码可以正常运行
    constexpr const char name[] = "Edward";
    constexpr auto joined1 = join_chars("name=", name);
    std::cout << joined1.c_str() << std::endl;

    // 这段代码无法运行
    // constexpr std::string_view value = "42"; // 本质和constexpr const char*一致
    // constexpr auto joined2 = join_chars("value=", value);
    // std::cout << joined2.c_str() << std::endl;

    return 0;
}

编辑1:
根据建议,通过在CharArray类中添加以下两个静态函数实现了扩展:

template <std::size_t N>
class CharArray
{
  //... 原有代码
  public:
    static constexpr CharArray create(const char* c_ptr) {
        std::array<char, N> tmp_array;
        std::copy(c_ptr, c_ptr + N, tmp_array.begin());
        CharArray<N> char_array{tmp_array};
        return char_array;
    }

    template <typename T>
    requires std::is_constructible_v<std::string_view, T>
    static constexpr CharArray create(const T& str) {
        return CharArray::create(str.data());
    }
};

再添加一个宏和重载函数:

template <typename T>
requires std::is_constructible_v<std::string_view, T>
constexpr std::size_t constexpr_strlen(const T& c_ptr) {
    return std::string_view{c_ptr}.length();
}

#define ConstexprChars(str) CharArray<constexpr_strlen(str) + 1>::create(str)

template <std::size_t N, typename... Strings>
constexpr auto join_chars(const CharArray<N>& first, Strings&&... rest) {
    if constexpr (!sizeof...(Strings)) { return first; }
    else { return first + join_chars(std::forward<Strings>(rest)...); }
}

之后可以这样调用:

int main() {
    constexpr const char* value = "42";
    constexpr auto joined2 = join_chars("value=", ConstexprChars(value));
    std::cout << joined2.c_str() << std::endl;

    return 0;
}

但这种方式改变了原有API,我希望能在保持原API不变的前提下实现该功能,即直接使用如下调用方式:

int main() {
    constexpr const char* value = "42";
    constexpr auto joined2 = join_chars("value=", value);
    std::cout << joined2.c_str() << std::endl;

    return 0;
}

编辑2:
我找到一个相关视频,里面处理过类似问题(还添加了静态存储),使用了lambda作为constexpr函数参数的技巧(这是允许的)。不过视频里没有使用我这种CharArray类,且该技巧仍需用lambda包裹char*,并未简化API,所以我猜测目前这已是最优方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 01:02:33