【发布时间】:2018-12-29 00:28:22
【问题描述】:
C++ 标准库支持各种function objects,包括关联二进制函子std::plus 和std::multiplies,它们是各种通用fold 算法的有用参数,例如std::accumulate、std::reduce 或@ 987654327@.
我正在实现Fenwick tree 以将关联二元运算符作为模板参数(默认为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 树以更改一个元素可以在最大值的情况下进行优化:如果树节点表示的范围中的先前最大值超过新值,则可以终止树传递。
那么,没有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>{});
另一个选项是通用的 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> 以类似的方式。
【问题讨论】:
-
std::min和std::max的特定特化将构成一个函数对象,用于比较其特化的类型。所有的函数指针都已经是函子了。 -
@πάνταῥεῖ 您在不阅读帖子的情况下判断速度非常快。您提出的作为骗子提出的问题与此无关,
std::max的建议表明您也没有理解此帖子(可能是因为您没有阅读它)。 -
std::accumulate(v.begin(), v.end(), 0, std::max);不起作用,但std::accumulate(v.begin(), v.end(), 0, std::max<T>);确实可以。如果必须命名T对您来说似乎不明智,那么您需要使用 lambda。当自动将重载集提升到函子中的提议通过时,也许这种情况会改变,但今天就是这样。 -
我建议你表现得更成熟一点。戳我的用户句柄,真的吗?