2017-06-12 61 views
4

我已經在這裏寫了一個答案: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; 
}); 

是的,我承認這只是一個副本,我不要求一個更好的解決方案,我想諮詢一下這個解決方案的有效性。

+2

我很確定它正在討論它正在應用的容器的迭代器。仿函數可以捕獲它正在迭代的容器並用它做一些事情。考慮一個無序的多集,你可以使用累積來試圖「加倍」其中每個元素的數量。這是不允許的,因爲向散列多集添加元素可能會使迭代器失效。 –

+0

您不要「修改範圍的任何元素」和「不要使任何迭代器[範圍]失效」,因此它在技術上是正確的。 cppreference上的例子也顯示了一個類似'std :: string'的代碼片段(可能不應該)。 – Drop

+0

簽名可能具有'const&',因爲您無論如何都要在每個函子應用程序上覆制結果向量。但是,即使你做了修改一些不相關的範圍內這一切都很好 - 「參與範圍」只有你通過的'accumulate' – Ap31

回答

3

我覺得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繼續與一些懸掛指針一起工作。不好。