在 constexpr 中连接 string_views

Posted

技术标签:

【中文标题】在 constexpr 中连接 string_views【英文标题】:concatenate string_views in constexpr 【发布时间】:2017-11-29 16:01:18 【问题描述】:

我正在尝试在 constexpr 中连接 string_views。 以下是我的代码的简化版本:

#include <iostream>
#include <string_view>

using namespace std::string_view_literals;

// concatenate two string_views by copying their bytes
// into a newly created buffer
constexpr const std::string_view operator+
    (const std::string_view& sv1, const std::string_view& sv2)

    char buffer[sv1.size()+sv2.size()] = 0;
    for(size_t i = 0; i < sv1.size(); i++)
        buffer[i] = sv1[i];
    for(size_t i = sv1.size(); i < sv1.size()+sv2.size(); i++)
        buffer[i] = sv2[i-sv1.size()];
    return std::string_view(buffer, sv1.size()+sv2.size());


int main()

    const std::string_view sv1("test1;");
    const std::string_view sv2("test2;");
    std::cout << sv1 << "|" << sv2 << ": " << (sv1+sv2+sv1) << std::endl;
    std::cout << "test1;"sv << "|" << "test2;"sv << ": " <<
        ("test1;"sv+"test2;"sv) << std::endl;
    return 0;

然而,这段代码并没有产生我预期的结果。它不是打印test1;test2;test1test1;test2;,而是打印出混合了随机字符的正确字符,就好像我正在访问未初始化的内存一样。

test1;|test2;: F��<��itest;
test1;|test2;: est1;te`�i

但是,如果我删除 constexpr 说明符并将 string_views 替换为 strings,上述代码将打印预期的输出。

test1;|test2;: test1;test2;test1;
test1;|test2;: test1;test2;

要么我在我的代码中遗漏了一些明显的错误,要么有一些关于constexpr 的东西我(还)不明白。是我为新的string_view 创建缓冲区的方式吗?我还能做什么?或者我想做的事情是不可能的?也许有人可以为我阐明这一点。

【问题讨论】:

您不能连接引用。而string_view 是一个引用类型。 char buffer[sv1.size()+sv2.size()] 不是标准 C++。 VLA 是一个扩展。 (函数参数不是 constexpr)。 @Jarod42,实际上,std::string_view::size() 是 constexpr 意味着只要使用 constexpr 参数调用函数,这实际上就可以了。当然,这应该使用本地 constexpr 变量来强制执行,但我相信他的具体示例实际上是可以的。 @Frank: sv1 不是 constexpr(我们目前没有办法表达)。所以sv1.size() 不是constexpr 您收到带有正确标志的警告:Demo。另见disable-variable-length-automatic-arrays-in-gcc 【参考方案1】:

您的任务基本上是不可能的,因为string_view,根据定义,需要从头到尾连续非拥有存储。所以管理数据的生命周期是不可能的。

如果你想做这样的事情,你需要创建某种concatenated_string&lt;&gt; 自定义范围作为你的返回类型。

至于您的代码产生奇怪结果的具体原因,仅仅是因为函数退出时buffer 不再存在。

【讨论】:

啊,好像有可能...这里是设计模板 inline constexpr string operator+(字符串, 字符串) 返回 ; ' 请实现 string 并实现从 std::string_view 到它的转换:)【参考方案2】:

return std::string_view(buffer, sv1.size()+sv2.size()); 中,返回的string_view 查看超出范围的buffer,因此您基本上有一个悬空引用。

【讨论】:

以上是关于在 constexpr 中连接 string_views的主要内容,如果未能解决你的问题,请参考以下文章

在引用定义中使用 constexpr 和 const

在这个例子中如何理解constexpr?

我们应该在函数中用 constexpr 定义变量吗

将字符串存储在 constexpr 结构中

在异常消息中使用 constexpr

c++11中的constexpr概念