Стандартная библиотека C ++ поддерживает различные функциональные объекты, в том числе ассоциативные бинарные функторы std::plus
а также std::multiplies
, которые являются полезными аргументами для различных общих складка алгоритмы, такие как std::accumulate
, std::reduce
, или же tbb::parallel_reduce
.
Я осуществлял Дерево Фенвика принять ассоциативный бинарный оператор в качестве аргумента шаблона (по умолчанию std::plus<void>
). Одним из возможных вариантов аргумента является оператор максимума (и минимума)
template<typename T=void>
struct maximum
{
constexpr T operator() (T const&x, T const&y) const
{ return x>y? x:y; }
};
template<>
struct maximum<void>
{
template<typename T>
constexpr T operator() (T const&x, T const&y) const
{ return x>y? x:y; }
};
когда дерево Фенвика может найти максимальное значение в префиксе любого элемента или в диапазоне элементов в логарифмическом времени.
Однако, к моему удивлению, такой бинарный максимальный функтор не существует в стандартной библиотеке. Я могу, конечно, использовать свой собственный, но это делает невозможным специализировать код для общего пользования. Например, обновление дерева Фенвика для замены одного элемента может быть оптимизировано в случае максимума: проход дерева может быть прекращен, если предыдущий максимум в диапазоне, представленном узлом дерева, превышает новое значение.
Итак, есть ли серьезные причины не иметь std::maximum
а также std::minimum
(Кроме как никто еще не предложил это)?
Обратите внимание, что std::max
нет варианта Вот:
std::accumulate(v.begin(), v.end(), 0, std::max<T>);
не работает (в C ++ 11, но это было раньше), в отличие от (с использованием выше maximum
)
std::accumulate(v.begin(), v.end(), 0, std::plus<void>{});
std::accumulate(v.begin(), v.end(), 0, maximum<void>{});
Другим вариантом был бы общий Выбрать Функтор, например, принимает в качестве аргумента функтор сравнения.
template<typename T, typename Compare = std::greater<T> >
struct select
{
constexpr T operator()(T const&x, T const&y) const
{ return comp(x,y)? x:y; }
private:
Compare comp;
};
а также select<void>
аналогичным образом.
Accumulate — это шаблонная функция, которая просто пытается вызвать функцию-аккумулятор, будь то Callable
или обычная функция (ну, сама обычная функция называется Callable), поэтому использование этого полностью допустимо
cout << std::accumulate(v.begin(), v.end(), 0, std::max<YOUR_TYPE_HERE>);
Если ваш тип был сложным (как и все, что не применимо к max), вы можете передать пользовательское лямбда-выражение (только C ++ после 11):
cout << std::accumulate(v.begin(), v.end(), 0, [](int a, int b){return a > b ? a : b;});
(заменить int
с вашим типом, и заменить return a > b ? a : b;
с твоей разыскиваемой логикой)
Если ваш компилятор отказался компилировать первый и вы используете что-то до C ++ 11, вы можете попробовать эту строку (небезопасно)
cout << std::accumulate(v.begin(), v.end(), 0, std::ptr_fun(std::max<int>));
std::ptr_fun
преобразует ЛЮБУЮ ФУНКЦИЮ в функциональный объект, чтобы его можно было использовать, см. эту ссылку http://www.cplusplus.com/reference/functional/ptr_fun/
Также есть класс под названием std::pointer_to_binary_function
это может помочь вам больше. Вот его ссылка http://www.cplusplus.com/reference/functional/pointer_to_binary_function/
Других решений пока нет …