缺少std :: maximum的设计注意事项是什么?

时间:2018-07-20 16:28:02

标签: c++ c++11 functor fold

C ++标准库支持各种function objects,包括关联的二进制函子std::plusstd::multiplies,它们对于各种通用的fold算法(例如{{ 3}},std::accumulatestd::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; }
};

当Fenwick树可以对数时间在任何元素的前缀或元素范围中找到最大值时。

但是,令我惊讶的是,标准库中不存在这样的二进制最大仿函数。我当然可以使用自己的代码,但是这使得专门化通用代码成为不可能。例如,在最大值的情况下,可以优化为一个元素的更改更新Fenwick树:如果树节点表示的范围中的先前最大值超过新值,则可以终止树通过。

那么,有没有任何严重的理由不使用std::maximumstd::minimum(除了还没有人提议之外)?

请注意,std::max不在这里

std::accumulate(v.begin(), v.end(), 0, std::max<T>);

与(在maximum上方使用)相反,它不起作用(在C ++ 11中但在以前起作用)

std::accumulate(v.begin(), v.end(), 0, std::plus<void>{});
std::accumulate(v.begin(), v.end(), 0, maximum<void>{});

另一个选择是使用比较函子作为参数的常规 select 函子

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>以类似的方式。

1 个答案:

答案 0 :(得分:-1)

Accumulate是一个模板函数,它只是尝试调用累加器函数,无论它是Callable还是常规函数(嗯,常规函数本身都是Callable的),因此使用它是完全有效的

cout << std::accumulate(v.begin(), v.end(), 0, std::max<YOUR_TYPE_HERE>);

如果您的类型很复杂(例如不适用于max的任何内容),则可以传入自定义lambda表达式(仅11以后的C ++):

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将ANY FUNCTION转换为函数对象,因此可以使用它,请参见此参考文献http://www.cplusplus.com/reference/functional/ptr_fun/

还有一个名为std::pointer_to_binary_function的课程,可以为您提供更多帮助。这是其参考文献http://www.cplusplus.com/reference/functional/pointer_to_binary_function/