【问题标题】:What are the design considerations for the lack of std::maximum?缺少 std::maximum 的设计考虑是什么?
【发布时间】:2018-12-29 00:28:22
【问题描述】:

C++ 标准库支持各种function objects,包括关联二进制函子std::plusstd::multiplies,它们是各种通用fold 算法的有用参数,例如std::accumulatestd::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::maximumstd::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&lt;void&gt; 以类似的方式。

【问题讨论】:

  • std::minstd::max 的特定特化将构成一个函数对象,用于比较其特化的类型。所有的函数指针都已经是函子了。
  • @πάνταῥεῖ 您在不阅读帖子的情况下判断速度非常快。您提出的作为骗子提出的问题与此无关,std::max 的建议表明您也没有理解此帖子(可能是因为您没有阅读它)。
  • std::accumulate(v.begin(), v.end(), 0, std::max); 不起作用,但 std::accumulate(v.begin(), v.end(), 0, std::max&lt;T&gt;); 确实可以。如果必须命名 T 对您来说似乎不明智,那么您需要使用 lambda。当自动将重载集提升到函子中的提议通过时,也许这种情况会改变,但今天就是这样。
  • 我建议你表现得更成熟一点。戳我的用户句柄,真的吗?

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


【解决方案1】:

Accumulate是一个模板函数,它只是试图调用累加器函数,不管是Callable还是一个正则函数(好吧,正则函数本身就是Callable),所以使用this是完全有效的

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

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

cout << std::accumulate(v.begin(), v.end(), 0, [](int a, int b){return a > b ? a : b;});

(用你的类型替换int,用你想要的逻辑替换return a &gt; 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/

【讨论】:

  • 它确实在 2011 年之前的 C++ 中编译。
  • 它确实在 2011 年前和 2011 年后编译,而 lambda(第二行)在 2011 年前没有编译,如果你想要在 2011 年前的 C++ 上更确定编译的东西,试试这行@ 987654331@
  • FWWI ptr_fun 在 C++11 中被弃用,在 C++17 中被移除
  • @NathanOliver 我知道,但似乎问题发布者想要 C++11 之前的东西
  • @user9335240 不,他们没有。什么让你有那个想法?帖子里的代码明明是C++11(比如constexpr
猜你喜欢
  • 1970-01-01
  • 2011-06-20
  • 2016-08-22
  • 1970-01-01
  • 1970-01-01
  • 2014-04-29
  • 1970-01-01
  • 2014-08-23
  • 2019-08-08
相关资源
最近更新 更多