Почему диапазоны:: накапливать не передать init как std::move(init) при вызове?

По состоянию на коммит d5e9afc 17 марта 2010 года из накопления.hpp

При прохождении диапазона init получает std::move когда-то так.

        T operator()(Rng && rng, T init, Op op = Op{}, P proj = P{}) const
        {
            return (*this)(begin(rng), end(rng), std::move(init), std::move(op),
                std::move(proj));
        }

Выше код будет вызывать это:

        T operator()(I begin, S end, T init, Op op = Op{}, P proj = P{}) const
        {
            for(; begin != end; ++begin)
                init = invoke(op, init, invoke(proj, *begin)); // why do we need this another copy of init?
            return init;
        }

Интересно, зачем нам эта еще одна копия init перед вызовом?

Этот init должен быть переопределен каким-либо образом, верно? Так почему же не стоит разорвать его в первую очередь?

                init = invoke(op, std::move(init), invoke(proj, *begin));

1 ответ

Этот фрагмент кода пытается избежать предположения, что C++17 может показаться. std::move-ную init потенциально может изменить его (для этого и нужна семантика перемещения в конце дня). И это оставляет нас с чем-то вроде этого:

init = /* An expression that maybe modifies init */;

Что приведет к неопределенному поведению до C++17. range-v3 также объявляет себя библиотекой для C++ 11 и C++14.

Другие вопросы по тегам