Я написал ответ здесь: 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 или чем-то еще:
В диапазоне
[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
продолжает работать с парой свисающих указателей. Не хорошо.
Других решений пока нет …