首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在编译时从constexpr char数组合成字符串文本?

如何在编译时从constexpr char数组合成字符串文本?
EN

Stack Overflow用户
提问于 2022-05-31 09:09:11
回答 2查看 168关注 0票数 0

我正在尝试创建一个将constexpr数组连接到一个数组的constexpr函数。我的目标是通过引用一个总是连接两个const char*的专用变量模板const char*来递归地完成这个任务,但是编译器不喜欢它,并抛出了一个我无法理解的错误消息。

我已经检查了主题,但不幸的是,它没有一个直接的答案。

代码

代码语言:javascript
运行
复制
#include <type_traits>
#include <cstdio>
#include <iostream>

constexpr auto size(const char*s)
{
    int i = 0;
    while(*s!=0) {
        ++i;
        ++s;
    }
    return i;
}

template <const char* S1, typename, const char* S2, typename>
struct join_impl;

template <const char* S1, int... I1, const char* S2, int... I2>
struct join_impl<S1, std::index_sequence<I1...>, S2, std::index_sequence<I2...>>
{
    static constexpr const char value[]{ S1[I1]..., S2[I2]..., 0 };
};

template <const char* S1, const char* S2>
constexpr auto join
{
    join_impl<S1, std::make_index_sequence<size(S1)>, S2, std::make_index_sequence<size(S2)>>::value
};

template <const char* S1, const char* S2, const char*... S>
struct join_multiple
{
    static constexpr const char* value = join<S1, join_multiple<S2, S...>::value>::value;
};

template <const char* S1, const char* S2>
struct join_multiple<S1, S2>
{
    static constexpr const char* value = join<S1, S2>;
};


constexpr const char a[] = "hello";
constexpr const char b[] = "world";
constexpr const char c[] = "how is it going?";

int main()
{
    // constexpr size_t size = 100;
    // char buf[size];
    // lw_ostream{buf, size};

    std::cout << join_multiple<a, b, c>::value << std::endl;
}

误差

代码语言:javascript
运行
复制
<source>:33:82: error: qualified name refers into a specialization of variable template 'join'
    static constexpr const char* value = join<S1, join_multiple<S2, S...>::value>::value;
                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
<source>:25:16: note: variable template 'join' declared here
constexpr auto join
               ^
<source>:33:34: error: default initialization of an object of const type 'const char *const'
    static constexpr const char* value = join<S1, join_multiple<S2, S...>::value>::value;
                                 ^
                                       = nullptr
2 errors generated.
ASM generation compiler returned: 1
<source>:33:82: error: qualified name refers into a specialization of variable template 'join'
    static constexpr const char* value = join<S1, join_multiple<S2, S...>::value>::value;
                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
<source>:25:16: note: variable template 'join' declared here
constexpr auto join
               ^
<source>:33:34: error: default initialization of an object of const type 'const char *const'
    static constexpr const char* value = join<S1, join_multiple<S2, S...>::value>::value;
                                 ^
                                       = nullptr
2 errors generated.
Execution build compiler returned:

我遗漏了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-06-03 09:18:51

作为替代,为了避免构建临时char数组,您可以使用类型(char序列)并只在末尾创建char数组变量,如下所示:

代码语言:javascript
运行
复制
constexpr auto size(const char*s)
{
    int i = 0;
    while(*s!=0) {
        ++i;
        ++s;
    }
    return i;
}

template <const char* S, typename Seq = std::make_index_sequence<size(S)>>
struct as_sequence;

template <const char* S, std::size_t... Is>
struct as_sequence<S, std::index_sequence<Is...>>
{
    using type = std::integer_sequence<char, S[Is]...>;
};

template <typename Seq>
struct as_string;

template <char... Cs1>
struct as_string<std::integer_sequence<char, Cs1...>>
{
    static constexpr const char c_str[] = {Cs1..., '\0'};
};

template <typename Seq1, typename Seq2, typename... Seqs>
struct join_seqs
{
    using type = typename join_seqs<typename join_seqs<Seq1, Seq2>::type, Seqs...>::type;
};

template <char... Cs1, char... Cs2>
struct join_seqs<std::integer_sequence<char, Cs1...>, std::integer_sequence<char, Cs2...>>
{
    using type = std::integer_sequence<char, Cs1..., Cs2...>;
};

template <const char*... Ptrs>
const auto join =
    as_string<typename join_seqs<typename as_sequence<Ptrs>::type...>::type>::c_str;

演示

票数 1
EN

Stack Overflow用户

发布于 2022-05-31 09:23:37

这里有两个问题。

首先,join是一个模板变量,因此它不包含所谓的value_type,它本身就是一个值,因此您的join_multiple应该是

代码语言:javascript
运行
复制
template <const char* S1, const char* S2, const char*... S>
struct join_multiple {
  static constexpr const char* value = join<S1, join_multiple<S2, S...>::value>;
};

其次,也不是很重要,index_sequence的整数类型是size_t而不是int,因此join_impl的部分专门化应该是(这不是必要的,但是使用size_t以外的类型会导致GCC到错误地拒绝它)。

代码语言:javascript
运行
复制
template <const char* S1, size_t... I1, const char* S2, size_t... I2>
struct join_impl<S1, std::index_sequence<I1...>, S2, std::index_sequence<I2...>> {
  static constexpr const char value[]{ S1[I1]..., S2[I2]..., 0 };
};

演示

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72445056

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档