c++ - 如何在编译时重复连接字符串?

标签 c++ string templates c++14 template-meta-programming

我编写了以下代码以在编译时使用字符串:

template<char... Chars>
struct CnstString {
    template<char... Aped>
    using push_back = CnstString<Chars..., Aped...>;
    constexpr static char value[] = {Chars...};
};

当我这样使用它时没问题:

#include <iostream>
using str = CnstString<'H', 'e', 'l', 'l', 'o', '\0'>;
int main()
{
    std::cout << str << std::endl;
    return 0; // it will output "Hello"
}

我想做的是使用递归模板结构体,在编译时拼接上面代码给出的字符串,并在递归终点处将 '\0' 附加到数组中。

我编写这段代码的原因是因为我想多次连接同一个字符串。显然我不能像 "Hello""Hello" 这样将相同的字符串连接在一起。

递归模板结构如下所示:

template<int N, typename Str>
struct RepeatStr {
    using ret = RepeatStr<N-1, Str>; // this is an error, I don't know how to pass parameters
};
template<typename Str>
struct RepeatStr<-1, Str> {
    using ret = Str:: template push_back<'\0'>;
};

但是,我发现我不知道如何使用 Str 中的字符向自身追加字符。

有什么问题吗?或者它根本不可能在编译时完成?

最佳答案

如果可能的话,我会更改 CnstString 的定义仅将 '\0' 放在 value

template<char... Chars>
struct CnstString {
    constexpr static char value[] = {Chars..., '\0'};
};

然后提供operator + (稍后将允许 Fold 表达式 (C++17))

template <char... Cs1, char...Cs2>
CnstString<Cs1..., Cs2...> operator +(CnstString<Cs1...>, CnstString<Cs2...>) { return {}; }

最后,你RepeatStr<N, Str>其类型为 Str{} + .. + Str{} :

template<int N, typename Str>
struct RepeatStr {
    // C++20
    using ret = decltype([]<std::size_t... Is>(std::index_sequence<Is...>){
        return ((static_cast<void>(Is), Str{}) + ...);
    }(std::make_index_sequence<N>()));
};

Demo

由于您仅限于 C++14,因此通过“递归”函数调用替换 C++17 的折叠表达式:

template <typename T>
auto sum_impl(T t)
{
    return t;
}

template <typename T, typename... Ts>
auto sum_impl(T t, Ts... ts)
{
    return t + sum_impl(ts...);
}

并将模板 lambda(C++20) 替换为常规模板函数:

template <typename Str, std::size_t... Is>
auto repeat_impl(std::index_sequence<Is...>)
{
    return sum_impl((static_cast<void>(Is), Str{})...);
}

template<int N, typename Str>
struct RepeatStr {
    using ret = decltype(repeat_impl<Str>(std::make_index_sequence<N>()));
};

Demo

关于c++ - 如何在编译时重复连接字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77325081/

相关文章:

c++ - 将 HW BP 放在哪里以捕获全局变量地址损坏?

c++ - 将未排序的链表转换为已排序的链表? (C++)

c++ - 通过重载 = 运算符从 std::string 创建 String 对象

c++ - 我如何强制 C++ 编译器对可能不需要的整数提升发出警告?

c++ - 如何保存字符串并按顺序读/写它们

c# - 在 xpath 表达式中使用字符串文字是不好的做法吗?

java - 使用 System.out.println 显示特殊字符

c++ - 检查模板参数是否为 std::vector<T>::iterator

c++ - 模板特化或分离函数的语义

templates - 如何从已解析的模板中获取模板 'actions' 的 map 或列表?