
https://habr.com/ru/company/jugru/blog/447498/
Size: a a a
ranges::begin
, ranges::end
, и ranges::swap
- это настоящие CPO. Вызов любой из них запускает описанное выше сложное метапрограммирование, чтобы найти найти и вызвать правильно кастомизированные begin
, end
или swap
, или реализацию по умолчанию, или вызов станет ill-formed (в SFINAE-совместимом стиле). Поскольку часть концептов из библиотеки определены в терминах корректного вызова CPO (например, Range и Swappable), правильно ограниченный обобщённый код должен использовать такие CPO. Конечно, если вы заранее знаете конкретный тип и альтернативный способ вытащить из него итератор, можно делать и так.ranges::cbegin
- это CPO без той части, которая "CP". Они выполняют поведение по-умолчанию, поэтому по смыслу это ни разу не customization point. Точно так же, формально, [range adaptor object](https://en.cppreference.com/w/cpp/ranges#Range_adaptors) - тоже CPO, но ничего настраиваемого там нет. Их отнесли к CPO только из соображений консистентности (как в случае с cbegin) или упрощения специфкации (адапторы).struct all_of_fn {
template< InputIterator I, Sentinel<I> S, class Proj = std::identity,
IndirectUnaryPredicate<projected<I, Proj>> Pred >
bool operator()( I first, S last, Pred pred, Proj proj = {} ) const
{
return ranges::find_if_not(first, last, std::ref(pred), std::ref(proj)) == last;
}
template< InputRange R, class Proj = std::identity,
IndirectUnaryPredicate<projected<ranges::iterator_t<R>, Proj>> Pred >
bool operator()( R&& r, Pred pred, Proj proj = {} ) const
{
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
}
};
inline constexpr all_of_fn all_of;
в случ
ае, когда ограниченный алгоритм из std::ranges запуст
или без квалификации. Поскольку алгоритмы std::range приним
ают пары Iterator-Sentinel, они обычно менее специазированны, чем их двойники в std, и поэ
тому вываливаются из механизма поиска оверлоадов.