【问题标题】:What are the Requirements on accumulate's Functor?累积函数的要求是什么?
【发布时间】:2017-11-13 08:41:50
【问题描述】:

我在这里写了一个答案:https://stackoverflow.com/a/44481507/2642059 它使用了accumulate

函子必须是二进制的,其签名如下:Ret op(const auto& a, const auto& b) 但是:

签名不需要有const &

对二元函子的要求是:

不得使任何迭代器无效,包括结束迭代器,或修改所涉及范围的任何元素

当累积到的对象本身就是一个容器时,我不清楚对函子的要求。例如允许这样的事情吗?

const auto range = { 0, 1, 2, 3 };
const auto Ret = accumulate(cbegin(range), cend(range), vector<int>(), [](auto& a, const auto& b){
    a.push_back(b);
    return a;
});

是的,我承认这只是一个副本,我不是在寻求更好的解决方案,我是在询问这个解决方案的有效性。

【问题讨论】:

  • 我很确定它正在谈论它所应用到的容器的迭代器。函子可以捕获它正在迭代的容器并对其进行处理。考虑一个无序的多集,您可以使用累积来尝试将其中每个元素的数量“加倍”。这是不允许的,因为将元素添加到哈希多重集可能会使迭代器无效。
  • 您不会“修改范围内的任何元素”和“不要使 [范围内] 的任何迭代器无效”,因此它在技术上是正确的。 cppreference 上的示例也显示了与std::string 类似的 sn-p(可能不应该)。
  • 您可能会发现这个相关提案很有趣:isocpp.org/files/papers/p0616r0.pdf
  • @ArneVogel 我发现这个提议太棒了!太感谢了。我随机找了一篇你的帖子进行投票,并在call_onceonce_flag 上找到了你的帖子。这太棒了,我从来不知道。现在我觉得我需要阅读你所有的答案!
  • @ArneVogel 我认为积累的吸引力主要源于它可以生成const 容器,而其他方法不能。我想这就是 Arne Vogel 引用提案背后的真正动机。

标签: c++ language-lawyer functor accumulate binary-operators


【解决方案1】:

我认为working draft 比 cppreference 或其他更明确:

[first, last]范围内binary_­op不得修改元素,也不得使迭代器或子范围无效。

accumulate 声明为:

template <class InputIterator, class T>
T accumulate(InputIterator first, InputIterator last, T init);

template <class InputIterator, class T, class BinaryOperation>
T accumulate(InputIterator first, InputIterator last, T init, BinaryOperation binary_op);

因此我会说你的例子是有效的,因为你没有影响[first, last]的范围。

另一方面,约束对于给定的范围非常有意义,因为您可以使用几个迭代器来定义它。
举个例子,想想如果它们是向量的开始和结束迭代器,您决定在 binary_op 内推送值会发生什么。
一旦向量调整大小,accumulate 就会继续使用几个悬空指针。不好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-13
    • 2016-02-14
    • 1970-01-01
    • 1970-01-01
    • 2012-07-18
    • 2012-05-31
    • 1970-01-01
    • 2020-01-26
    相关资源
    最近更新 更多