Почему C++ не стандартизировал перегрузки алгоритмов, которые работают с целыми контейнерами?

Стандартный ISO C++ имеет богатую библиотеку алгоритмов, включающую большое количество синтаксического сахара, такого как std::max_element, std::fill, std::count и т. д.

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

Я действительно не понимаю, почему они добавили такие базовые вещи, когда мы остались без целых версий контейнера (конечно, самый распространенный случай) или аналогичным образом остались с жестокостью, которая является идиомой векторного стирания-удаления:

v.erase(std::remove(v.begin(), v.end(), elem), v.end());

Кажется, что каждый проект, который я пишу на C++, заканчивает тем, что я включаю свой собственный заголовочный файл, который включает базовый синтаксический сахар для подобных вещей.

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

Я пытаюсь понять, почему в стандарте есть веская причина для таких вещей, как std::max_element и std::fill в диапазонах, но не для версий, которые работают с целыми контейнерами, или для другого синтаксического сахара, который уменьшает многословность написания кода C++.


person Tumbleweed53    schedule 19.11.2020    source источник
comment
Я не могу сказать, почему у нас его не было раньше, но оно есть (в основном) сейчас: en.cppreference.com/w/cpp/ranges   -  person NathanOliver    schedule 19.11.2020
comment
Как насчет того, когда вы хотите запустить эти алгоритмы в поддиапазоне контейнера? Кажется, вы в основном просите удвоить количество функций в разделе библиотеки «Алгоритмы», добавив версию всего контейнера для каждой из них, которая принимает диапазон. (И учетверенный для тех, кто берет два диапазона)   -  person M.M    schedule 19.11.2020
comment
Обоснованием такой конструкции можно было бы заполнить целую книгу. Собственно говоря, Александр Степанов так и сделал (поскольку вы пометили эту STL).   -  person StoryTeller - Unslander Monica    schedule 19.11.2020
comment
Похоже, что каноническая цель нуждается в обновлении.   -  person cigien    schedule 19.11.2020
comment
@cigien Более или менее обманщик, не так ли? Хорошо, ОП спрашивает, почему, но только здесь можно ответить на основе мнения.   -  person πάντα ῥεῖ    schedule 19.11.2020
comment
@πάνταῥεῖ Да, в значительной степени. Мне не хочется забивать, потому что он не обновляется :p Ответы тоже не особо интересны. Однако есть достойный здесь.   -  person cigien    schedule 19.11.2020
comment
Эти тривиальные алгоритмы часто оптимизируются поставщиками библиотек, например. используйте memset применительно к char*   -  person dewaffled    schedule 19.11.2020
comment
@cigien Это правильный ответ с достаточным ответом, да (даже от Дитмара Кюля, ветерана стандартов C ++ прошлого века, я помню, что он был постоянным участником группы usenet c ++ lang :-D)   -  person πάντα ῥεῖ    schedule 19.11.2020


Ответы (2)


Это было исправлено в C++20.

См. один пример на cppreference.

template< ranges::input_range R, class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>> Pred >
constexpr ranges::range_difference_t<R>
  count_if( R&& r, Pred pred = {}, Proj proj = {} );

bool is_even(int n) {
   return (n % 2 == 0);
}
std::vector<int> l(10);
std::iota(l.begin(), l.end(), 0); // is in numerics which hasn't been rangified.

auto cnt = std::ranges::count_if(arr, is_even);

person Surt    schedule 19.11.2020

Почему C++ не стандартизировал перегрузки алгоритмов, которые работают с целыми контейнерами?

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

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


Однако вместо перегрузок C++ имеет те же алгоритмы для полных диапазонов в отдельном пространстве имен std::ranges, что и C++20. Пример использования заливки:

std::ranges::fill(container, value);

зверство, которое является идиомой вектора стереть-удалить

Хотя диапазоны не вводят новые перегрузки функций-членов, существует альтернатива стиранию, не являющаяся членом:

std::erase(vector, elem);
person eerorika    schedule 19.11.2020