Объединить string_views в constexpr

Я пытаюсь объединить string_views в constexpr, Ниже приведена упрощенная версия моего кода:

#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;test1 а также test1;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? Что еще я мог сделать? Или то, что я пытаюсь сделать, невозможно? Может быть, есть кто-то, кто может пролить свет на это для меня.

2 ответа

Решение

Ваша задача принципиально невозможна, так как string_viewпо определению, необходимо иметь непрерывное несобственное хранилище от начала до конца. Таким образом, будет невозможно управлять временем жизни данных.

Вам нужно создать какой-то concatenated_string<> Пользовательский диапазон в качестве типа возврата, если вы хотите сделать что-то вроде этого.

Что касается конкретной причины, по которой ваш код дает странные результаты, это просто потому, что buffer больше не существует при выходе из функции.

В return std::string_view(buffer, sv1.size()+sv2.size()); возвращенный string_view рассматривает buffer который выходит за рамки, так что у вас по существу есть свисающая ссылка.

Другие вопросы по тегам