Неявное преобразование basic_string в basic_string_view тьфу, почему?

Комитет по стандартам C++ имел возможность сделать код более безопасным с помощью string_view, но они решили добавить неявное преобразование из basic_string в basic_string_view.

Так эффективно они говорят это

// No worries, everyone always reads the docs...
struct Foo{
      string_view sv;
      //I really want to make this constexpr
      constexpr Foo(string_view sv):sv(sv){} 
};

/* ...some Friday afternoon... */

string s{"Looks like it works"};
Foo f{s + "..."};

менее важно, чем это

string f{"foo"};
string_view b{"bar"};
i_wonder(f == b);
//glad I didn't have to type static_cast<string_view>(f)!!

Скажите, пожалуйста, есть ли веские причины для неявного преобразования из basic_string в basic_string_view.

Хуже всего то, что вам нужен string_view, чтобы использовать constexpr (я знаю, или char*...)

ОБНОВЛЕНИЕ: этот вопрос был отложен, поскольку он не соответствует рекомендациям SO. Справедливо. Я думаю, что это то, что нужно подчеркнуть. Я думаю, что это неявное преобразование — шаг назад. Я начинаю видеть, как люди (даже очень опытные люди) пишут оборванные указатели из-за этого, как будто сейчас 90-е.

Каковы наилучшие методы использования string_view, в частности, WRT риска неявного преобразования от владельца к не-владельцу? Вечная бдительность не ответ.

Я должен сказать, что очень удивлен тем, как мало людей здесь заботятся о безопасности типов. Это повторяющаяся цель «современного» C++.


person user9816683    schedule 22.05.2018    source источник
comment
IMO неявное преобразование должно работать только для & и const &, но не для &&.   -  person Mooing Duck    schedule 22.05.2018
comment
Представления не предназначены для владения.   -  person Jarod42    schedule 22.05.2018
comment
@MooingDuck Если это сработает для const &, то сработает и для &&.   -  person Daniel H    schedule 22.05.2018
comment
Я согласен, что это не идеально, но программистам на C++ уже нужно думать о праве собственности всякий раз, когда они используют ссылки; по-видимому, теперь им нужно будет не забывать относиться к _view так же, как они относятся к &.   -  person Daniel H    schedule 22.05.2018
comment
@DanielH, нельзя ли явно перегрузить их отдельно?   -  person monkey0506    schedule 22.05.2018
comment
@monkey0506 Вы правы; Я забыл, что вы можете явно объявить это =delete; если вы этого не сделаете, он вернется к конструктору const&.   -  person Daniel H    schedule 22.05.2018
comment
@ Jarod42 да, и именно поэтому должно быть только явное преобразование. неявное преобразование из типа владения в невладение плохим дизайном IMO.   -  person user9816683    schedule 22.05.2018
comment
@ user9816683: Нравится неявная привязка ссылки к объекту, который всегда был в языке? Чем это еще хуже..?   -  person ildjarn    schedule 22.05.2018
comment
@ildjam Ну, это не всегда было на языке. Это ново и, следовательно, дает возможность для улучшения. Тем не менее, это противоречит заявленным целям современного C++, в частности безопасности типов в данном случае. Новые функции должны быть выше, чем просто не хуже существующих.   -  person user9816683    schedule 22.05.2018
comment
О, хорошо, я думаю, это просто еще один дефолт, который они ошиблись.   -  person user9816683    schedule 22.05.2018
comment
Комитет по стандартам мог бы получить лучшее из обоих, просто перегрузив operator std::string_view() const && (=delete был бы хорошим кандидатом). Неявное преобразование по-прежнему будет работать для невременных объектов, но вы не закончите тем, что создадите string_view для объекта, который будет уничтожен после завершения конструктора.   -  person monkey0506    schedule 22.05.2018
comment
@monkey0506 : foo(bar()) с учетом void foo(string_view) и string bar() не будет компилироваться, и это наверняка вызовет жалобы на эргономику (отсутствие) C++. :-]   -  person ildjarn    schedule 22.05.2018
comment
@ user9816683: Вы не можете так радикально изменить характер вопроса. Изначально вы задали вопрос о том, почему стандарт такой, какой он есть. Вы не можете превратить это в вопрос о том, что делать из-за того, что говорит стандарт. Но оба вопроса основаны на мнении.   -  person Nicol Bolas    schedule 22.05.2018
comment
Есть ли в вашей кодовой базе ссылки? Строковые представления являются ссылками; необходимо соблюдать такую ​​же осторожность. Я записал в нее стандартную строку общего владения с представлениями общего владения, но это недешево из-за спора о подсчете ссылок, который вы получаете.   -  person Yakk - Adam Nevraumont    schedule 22.05.2018
comment
@Yakk-AdamNevraumont Дело не в ссылках. Речь идет об удивительных неявных преобразованиях.   -  person user9816683    schedule 22.05.2018
comment
@ildjarn в комментариях к ответу einpoklum ниже мне совершенно ясно указали, что я неправильно понял срок службы временных материалов в подобных случаях. Вы правы, и мой комментарий совершенно неверен.   -  person monkey0506    schedule 22.05.2018
comment
@monkey0506: Я видел, не беспокойся. :-] Кстати, обратите внимание на правильный стандарт, если вы педантичный тип (как и многие публикации в этом теге): eel.is/c++draft/class.temporary#6   -  person ildjarn    schedule 22.05.2018
comment
@user заменяет строковое представление ссылкой на строку. Существуют те же неявные проблемы продолжительности жизни. Если у вас есть тип Foo, который хранит строку const ref и берет ее при построении, ваш код компилируется, и ссылка также висит.   -  person Yakk - Adam Nevraumont    schedule 22.05.2018
comment
FWIW Титус Уинтерс соглашается, что есть проблема: P open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0922r0.pdf   -  person NoSenseEtAl    schedule 26.05.2018
comment
также выше pdf есть некоторые рассуждения, почему string_view такой ужасный (он позволяет использовать некоторые варианты использования)   -  person NoSenseEtAl    schedule 26.05.2018


Ответы (1)


Скажите, пожалуйста, есть ли веские причины для неявного преобразования из basic_string в basic_string_view.

Итак, мы хотим:

  1. иметь возможность писать функции, работающие с string_views, а не strings, чтобы не ограничивать вызывающую сторону в отношении того, как хранятся строковые данные/кому они принадлежат, и не нужно писать варианты этих функций для strings, char * и т. д.
  2. Уметь легко передавать strings этим функциям

поэтому нам нужно неявное преобразование.

person einpoklum    schedule 22.05.2018
comment
Вопрос, можем ли мы с уверенностью сказать, что string_view чем-то похож на контейнер? - person Joseph D.; 22.05.2018
comment
1. Что мешает писать шаблонные функции, которые могут работать со строкой и строковым_представлением? AFAICT абстракция string_view должна быть подмножеством строк. - person user9816683; 22.05.2018
comment
2. Я до сих пор не понимаю, как это не просто отдает приоритет небольшому удобству неявного приведения вместо явного в пользу надежной семантики владения WRT. - person user9816683; 22.05.2018
comment
@user9816683: Я до сих пор не понимаю, почему это не просто расстановка приоритетов... Кто сказал, что это не так? Ни одна из сторон не ошибается на 100%; у каждого своя точка. Но они исходят из отдельного набора значений. Кажется, вы цените безопасность превыше всего. Другие ценят удобство использования и производительность. Тот факт, что вашей первой мыслью при создании сравнительного примера было преобразовать string_view в string, показывает, что производительность здесь не является вашей основной ценностью. - person Nicol Bolas; 22.05.2018
comment
Производительность @NicolBolas здесь означает, что конечному пользователю не нужно использовать static_cast, но безопасность можно было бы обеспечить с таким же удобством использования и производительностью, предоставив (или, скорее, удалив) перегрузку &&. Преобразование из string&& в string_view никогда не является допустимой конструкцией. - person monkey0506; 22.05.2018
comment
@monkey0506: Чепуха. void func(string_view sv); string func2(); func(func2()); Совершенно верно. Удаление преобразования && приведет к тому, что этот совершенно корректный код не будет компилироваться. - person Nicol Bolas; 22.05.2018
comment
@NicolBolas, но гарантируется ли срок службы string&& до конца func? Возможно, я неправильно понимаю, но я думал, что время жизни возвращаемого объекта закончится, как только будет создан sv. - person monkey0506; 22.05.2018
comment
@monkey0506 monkey0506 время жизни временного объекта гарантируется до конца выражения, в котором оно используется. Это означает, что в func(func2()); string гарантированно будет действительным до ;, то есть до выхода func(), а не только до создания sv. - person Remy Lebeau; 22.05.2018
comment
Я беру назад то, что я сказал о том, что это недействительно тогда, потому что я понимал, что время жизни временного объекта будет продлено только через string const& или string&& параметры функции, а не через преобразование, подобное этому. - person monkey0506; 22.05.2018
comment
@monkey0506 Monkey0506 ваше понимание управления сроком службы временных файлов в этом случае неверно. У тебя есть чему поучиться. - person Remy Lebeau; 22.05.2018
comment
@NicolBolas Вы упустили суть. Пример о том, как кто-то может не осознавать, что он должен использовать string_view. Неявное и явное преобразование не имеет ничего общего с производительностью. Мой аргумент касается удобства использования и безопасности. И я утверждаю, что необходимость выполнять явное преобразование гораздо менее важна, чем четкая семантика владения. - person user9816683; 22.05.2018
comment
@user9816683: И вы можете утверждать, что все, что вам нравится. Но это все же аргумент, а не факт. Одни с вами согласятся, другие нет. Но ваш аргумент, основанный на ваших ценностях, не сделает решение комитета неправильным в каком-то объективном смысле, а только неправильным относительно вашей системы ценностей. Но вопрос, который вы задали, был о том, почему это было сделано. Это было сделано потому, что в данном случае комитет ценил удобство использования выше безопасности. Это ответ. Вы можете не верить, что этого достаточно или чтобы оправдать затраты на обеспечение безопасности. Но это все же остается ответом. - person Nicol Bolas; 22.05.2018
comment
@user9816683 user9816683: Заклеивать API-интерфейсы некоторых библиотек, когда нужны ссылки, в лучшем случае глупо (IMO). Это C++ — нужно всегда быть осторожным и осознавать право собственности. - person ildjarn; 22.05.2018
comment
@NicolBolas Похоже, вы пытаетесь изобрести ложную дихотомию между безопасностью и производительностью. - person user9816683; 22.05.2018
comment
@ildjarn Это не пластырь. Это новая функция. - person user9816683; 22.05.2018
comment
@ user9816683: В его комментарии не упоминается слово «производительность», а скорее «удобство использования». Похоже, вы хватаетесь за соломинку, чтобы дискредитировать любого, кто представляет альтернативное мнение. ;-] - person ildjarn; 22.05.2018
comment
@ildjarn Вы читаете не тот комментарий. Он упоминает производительность. - person user9816683; 22.05.2018
comment
О, вы отвечали на комментарий, написанный более получаса назад, на который вы уже ответили, во второй раз? Не тот, что за 4 минуты до вашего комментария? Я был глуп, предполагая, что этот разговор был хронологическим... ›_› - person ildjarn; 22.05.2018
comment
@RemyLebeau Ранее я читал, что конструкторы специально вводят исключение в значение полного выражения, но теперь я понимаю, что это было совершенно неверно. - person monkey0506; 22.05.2018