Неожиданно для себя обнаружил неочевидное, для себя, поведение связки std::string и std::string_view. Из коробки к строке нельзя конкатенировать отображение строки.
Здравствуйте, Videoman, Вы писали:
V>Неожиданно для себя обнаружил неочевидное, для себя, поведение связки std::string и std::string_view. Из коробки к строке нельзя конкатенировать отображение строки. V> V>Вопросы к знатокам: V>- с чем связано такое решение в стандарте? V>- чем такая конкатенация отличается от конкатенации с сырой С-шной строкой?
Догадка:
1) string_view не поддерживает никакие операции с аллокацией памяти.
2) Если такое сложение разрешить, велика вероятность сделать ошибку типа:
std::string_view result = "foo"s + "bar"sv; //< store reference on temporary string
По этой же причине, нет неявного преобразования string_view->string.
Здравствуйте, Chorkov, Вы писали:
C>Догадка: C>1) string_view не поддерживает никакие операции с аллокацией памяти.
Это понятно. Из-за этого же разрешено только явное преобразование к стоке.
C>2) Если такое сложение разрешить, велика вероятность сделать ошибку типа: C>
C>std::string_view result = "foo"s + "bar"sv; //< store reference on temporary string
C>
Это тоже понятно, также как и операция сложения двух нативных строк, тут ничего нового. А почему нельзя к строке прибавлять string_view, а нативную можно, строка же поддерживает переаллокацию?
Здравствуйте, Videoman, Вы писали:
V>- с чем связано такое решение в стандарте?
Автор оригинального proposal хотел упороться по оптимизации и сделать конкатенацию через string builder, но не смог. Остался такой вот задаел на будущее, который никому в таком виде не нужен.
А потом всем было несколько лет лень написать proposal на исправление этой ситуации (потому что по формальным правилам это не дефект стандарта).
V>- чем такая конкатенация отличается от конкатенации с сырой С-шной строкой?
Если не считать обычного различия, что С-string не может содержать внутри символ \0, а string_view может, то различий особо нет. Причина отсутствия operator+(string, view) в c++17 не связана с этим.
Тем более, что там же уже был operator+=(string, view).
V> return str + std::string(view);
Как быстрая заплатка — ок. Но есть же в string методы append или operator+=, которые позволяют приписать что угодно к строке без конвертации view в строку, что сэкономит аллокацию под временную копию строки.
Здравствуйте, watchmaker, Вы писали:
W>Если не считать обычного различия, что С-string не может содержать внутри символ \0, а string_view может, то различий особо нет. Причина отсутствия operator+(string, view) в c++17 не связана с этим. W>Тем более, что там же уже был operator+=(string, view).
Тут не понял. Где кто был уже? Я в С++17 сейчас, оператора такого нет
W>Как быстрая заплатка — ок. Но есть же в string методы append или operator+=, которые позволяют приписать что угодно к строке без конвертации view в строку, что сэкономит аллокацию под временную копию строки.
Я просто демонстрировал проблему по быстрому. Основная проблема у меня в том, что где-то по делу меняя string на string_view, код перестаёт работать на конкатенациях и теперь мне приходится его переписывать. У меня нет каких-то особых требований по быстрой работе со строками, это не критические места, которые вызываются не чаще исключений.
Здравствуйте, Videoman, Вы писали:
W>>Тем более, что там же уже был operator+=(string, view). V>Тут не понял. Где кто был уже? Я в С++17 сейчас, оператора такого нет
В С++17 оператор str += sv есть, см. номер 5, а вот оператора str + sv нет.
Здравствуйте, B0FEE664, Вы писали:
BFE>В С++17 оператор str += sv есть, см. номер 5, а вот оператора str + sv нет.
Да, понятно, спасибо! Историю как "закалялся" string_view пропустил, поэтому мотивацию стандарта до конца не понял. А проблема началась неожиданно. Раньше некоторые старые функции использовали const string& в качестве типа аргумента и "новый" string_view туда не передать, без явного преобразования. Теперь вот string_view распространяется по коду как вирус .
Здравствуйте, watchmaker, Вы писали:
W>Автор оригинального proposal хотел упороться по оптимизации и сделать конкатенацию через string builder, но не смог. Остался такой вот задаел на будущее, который никому в таком виде не нужен.
не будет string builder'а?
Грустно.
Это же разрешимая ситуация: достаточно при инициализации builder'а другим объектом builder'а делать полную копию всех подстрок в одну строку.
Или есть ещё какие-то сценарии?
Здравствуйте, Videoman, Вы писали:
V>Да, понятно, спасибо! Историю как "закалялся" string_view пропустил, поэтому мотивацию стандарта до конца не понял. А проблема началась неожиданно. Раньше некоторые старые функции использовали const string& в качестве типа аргумента и "новый" string_view туда не передать, без явного преобразования. Теперь вот string_view распространяется по коду как вирус .
Я историю string_view не знаю, но по коду видно, что с string_view всё несколько странно. Например, почему operator[] не noexcept?:
constexpr const_reference operator[]( size_type pos ) const;
...
Exceptions
Does not throw
Здравствуйте, B0FEE664, Вы писали:
BFE>Я историю string_view не знаю, но по коду видно, что с string_view всё несколько странно. Например, почему operator[] не noexcept?: BFE>
ЕМНИП, некоторые реализации могут бросать из этих методов исключения в отладочном режиме. Отсюда и отсутствие noexcept там, где как раз noexcept и ожидаешь
Здравствуйте, B0FEE664, Вы писали:
BFE>Я историю string_view не знаю, но по коду видно, что с string_view всё несколько странно. Например, почему operator[] не noexcept?:
По той же причине, почему и у std::vector он без noexcept. Отладочной версии библиотеки нужно разрешить из них кидать.
Здравствуйте, Videoman, Вы писали:
V>- с чем связано такое решение в стандарте? V>- чем такая конкатенация отличается от конкатенации с сырой С-шной строкой?
Не, ну ты спроси ещё, а почему по std::string_view нельзя делать поиск в мапе, где ключ std::string.
Это ж кресты, подожди лет 5, когда до крестокомитета дойдёт, что они опять обосрались, и ещё лет 5, когда выйдет новый крестостандарт, и ещё лет 5, когда этот стандарт будут поддерживаться всеми крестокомпиляторами.
BFE>Я историю string_view не знаю, но по коду видно, что с string_view всё несколько странно. Например, почему operator[] не noexcept?:
Потому что noexcept Prevents Library Validation. Смотри сколько добавленных noexcept удалили. Не только из строк, а вообще из разных частей библиотеки. А string_view появился уже позже и в нём сразу не добавляли.
Но добавлю, всё это скорее относится к тем, кто пишет стандартную библиотеку, а не к тем, кто её использует. Это первым нужно тестировать правильность реализации. А пользователям это ни к чему.
Поэтому скорее всего noexcept вернётся, а авторов STL попросят писать тесты на свой код какми-нибудь другим способом.
По этой ссылке не выписана секция Preconditions, ну или сделано это не так явном виде. Наверное потому что написано для пользователей, а не для авторов STL.
А как раз секция Preconditions и документ выше в данном случае объясняют отсутствующий в сигнатуре noexcept.
BFE>Exceptions BFE>Does not throw
Верно. И если библиотека не хочет диагностировать баги этом в методе, то она может поставить noexcept. Как, например, это сделано в libcxx или в libstdc++.
Здравствуйте, T4r4sB, Вы писали:
TB>Тем временем, уже много лет как есть llvm::Twine (ссылочный класс, хранит фрагменты итоговой строки), где всё смогли TB>https://llvm.org/doxygen/classllvm_1_1Twine.html
Сомневаюсь, что всё смогли.
Вот такое, вроде бы, судя по коду, работать не должно:
Здравствуйте, watchmaker, Вы писали: BFE>>Я историю string_view не знаю, но по коду видно, что с string_view всё несколько странно. Например, почему operator[] не noexcept?: W>Потому что noexcept Prevents Library Validation.
Очень, очень странная аргументация. Пытаться сделать определённое поведение для ситуаций, когда поведение не определено — дурацкая затея сама по себе, а уж сделать это только для того, чтобы тестировать — вдвойне дурацкая, так как это тестирование кода, который не исполняется в release версии.
C++ это вам не Basic с его On Error Resume Next!
В конце концов — падение при бросании исключения из функции noexcept — это просто отличное поведение для undefined behavior. И вообще, отказ от оптимизации только для того, чтобы удобно было запускать тесты — это попытка заплатить за то, что не используется. W>Но добавлю, всё это скорее относится к тем, кто пишет стандартную библиотеку, а не к тем, кто её использует. Это первым нужно тестировать правильность реализации. А пользователям это ни к чему.
В смысле? assert'ы ведущие к немедленному крашу приложения удобны для тестирования своего пользовательского кода.
В конце концов, если им так хочется ловить исключения, то нет ничего сложного, достаточно тело каждой noexcept функции обернуть в try-catch блок через макросы:
Всё.
И никаких проблем. W> Поэтому скорее всего noexcept вернётся, а авторов STL попросят писать тесты на свой код какми-нибудь другим способом.
Таких специалистов, действительно, стоит попросить. BFE>>отсюда W>По этой ссылке не выписана секция Preconditions, ну или сделано это не так явном виде. Наверное потому что написано для пользователей, а не для авторов STL.
не выписана секция Preconditions? А это тогда что:
No bounds checking is performed: the behavior is undefined if pos >= size().
W>А как раз секция Preconditions и документ выше в данном случае объясняют отсутствующий в сигнатуре noexcept.
Выглядит объяснение жалко: "Ой, это что-то новое, мы так не умеем, мы к этому не привыкли, наши тесты ломаются".
Скрытый текст
Unfortunately the feature is so new that there is very little field experience to develop a coherent set of guidelines.
W>Верно. И если библиотека не хочет диагностировать баги этом в методе, то она может поставить noexcept.
Вот за эту цитату спасибо. Теперь понятно почему иногда есть отличие в реализации от стандарта.