C ++标准库支持各种function objects,包括关联的二进制函子std::plus
和std::multiplies
,它们对于各种通用的fold算法(例如{{ 3}},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; }
};
当Fenwick树可以对数时间在任何元素的前缀或元素范围中找到最大值时。
但是,令我惊讶的是,标准库中不存在这样的二进制最大仿函数。我当然可以使用自己的代码,但是这使得专门化通用代码成为不可能。例如,在最大值的情况下,可以优化为一个元素的更改更新Fenwick树:如果树节点表示的范围中的先前最大值超过新值,则可以终止树通过。
那么,有没有任何严重的理由不使用std::maximum
和std::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>
以类似的方式。
答案 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/