Почему string_view вместо обобщенного container_view‹T›?

Я нашел string_view из нового стандарта С++ 17 немного избыточным.

У нас есть довольно подробный набор простых механизмов для передачи данных вызываемому без особых накладных расходов, и теперь есть один другой который также специфичен только для одного типа контейнера.

Я не понимаю, почему этот механизм предоставляется только для строки, а не для какого-то более обобщенного типа для других контейнеров. Один разумный ответ заключается в том, что у нас уже были такие решения. Например, в презентации C++17 и выше string_view объясняется как observer_ptr<T> (or T*) for string.

Укажите аргументы против более общего container_view, в отличие от string_view, представленного в C++17.


person LookAheadAtYourTypes    schedule 19.08.2016    source источник
comment
Я думаю, что сравнение observer_ptr просто создает путаницу и отвлекает от вопроса о том, должно ли быть обобщенное container_view вместо конкретного string_view.   -  person juanchopanza    schedule 19.08.2016
comment
Потому что операции со строками — самая распространенная задача программирования? Я думаю, что ответ прост.   -  person Jesse Good    schedule 19.08.2016
comment
container_view не будет работать с одним const char*, но string_view имеет дополнительное предположение, что такой указатель указывает на строку, завершающуюся \0, когда он создается с помощью этого конструктора с одним указателем.   -  person Johannes Schaub - litb    schedule 20.08.2016


Ответы (2)


Обобщенный container_view правильнее называть диапазоном. У нас есть TS на маршруте, полностью посвященный концепциям дальности.

Теперь у нас есть string_view как отдельный тип, потому что он имеет специализированный, специфичный для строк интерфейс, чтобы соответствовать специфичному для строки интерфейсу basic_string. Или, по крайней мере, чтобы соответствовать интерфейсам const/non-allocating.

Обратите внимание, что container_view или как бы вы его ни назвали, не сможет стереть свое соединение с контейнером, который его сгенерировал. Или, по крайней мере, не без оплаты накладных расходов на стирание типа при каждом доступе/операции.

Напротив, string_view основано на const char*s и целых числах. Этому классу все равно, откуда взялась строка; он обеспечивает просмотр непрерывного массива символов независимо от того, кому он принадлежит. Он может сделать это, потому что знает, что источником является непрерывный массив, и поэтому использует указатели в качестве ядра своего итератора.

Вы не можете сделать это для произвольных контейнеров. Ваш container_view<vector> будет иметь итераторы, отличные от container_view<list> или чего-то еще. Это должно. Это означает, что если вы принимаете container_view в качестве параметра функции, вы должны либо выбрать конкретный контейнер для использования (заставляя пользователя указать именно этот тип контейнера), либо сделать свою функцию шаблоном, либо использовать диапазон итератора со стертым типом (таким образом помедленнее).

Существуют также предложения после C++17 для типов GSL span и mdspan. Первый представляет собой модифицируемое "представление" непрерывного массива. Последний представляет собой модифицируемое «представление» непрерывного массива, который вы считаете многомерным.

person Nicol Bolas    schedule 19.08.2016

string_view предлагает больше, чем простой указатель на строку. Вам нужно смотреть на это как на нечто большее, чем просто указатель, не являющийся владельцем: если бы это было все, string_view не мог бы позволить вам «нарезать» части строки и применять к ней операции (оставаясь при этом представлением, таким образом без учета стоимости копии):

char *s = "welcome to stackoverflow";
auto s = std::string_view{s + 8, 2}; // a view on "to"
// you can then apply many operations on this view, that wouldn't make sense more on your general non_owning<T>:
s.remove_prefix(std::min(s.find_first_not_of(" "), s.size()));
// it also "inherits" (copies the API) a lot directly from std::basic_string
auto view2 = s.substr(3, 4); // a generic non-owning ptr would copy here, instead of giving you a new view
person Ven    schedule 19.08.2016
comment
Есть ли что-то, что мешает нам обеспечить такое же поведение представления для других контейнеров? - person LookAheadAtYourTypes; 19.08.2016
comment
Не совсем. Вот почему Boost, например, имеет array_view (и boost.fusion — другой тип представлений для фильтра, карты и т. д.). Единственная проблема заключается в том, что вам нужно сделать это вручную, потому что, как я показал здесь, вам нужно определенное поведение для каждого контейнера. - person Ven; 19.08.2016
comment
@tomekpe Также есть несколько конкурирующих предложений о включении в стандарт общего представления диапазона (и даже изменяемого представления диапазона, называемого «span», как в Microsoft GSL). Предложениям может потребоваться согласование дизайна, прежде чем поставщики начнут его реализовывать. - person Morwenn; 19.08.2016
comment
Я уверен, что должно быть два разных ses. - person Tomilov Anatoliy; 19.08.2016