0

Most answers, including this one, point out that std::move is not meant to be used in self-assignment.
I do, however, see the Possible Implementation of accumulate in official reference via self move assignment:

template<class InputIt, class T>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init)
{
    for (; first != last; ++first) {
        init = std::move(init) + *first; // std::move since C++20
    }
return init;
}

Is it safe only since C++20? What is happening internally?
The EXP63-CPP states that:

it should be assumed that the only operations that may be safely performed on a moved-from object instance are reinitialization through assignment into the object or terminating the lifetime of the object by invoking its destructor

Looks like reinitialization is completely legal.

user2376997
  • 501
  • 6
  • 22
  • 1
    That's not an official reference. The closest to an official reference you can get without paying for it is the drafts of the standards. – molbdnilo Sep 27 '20 at 08:18
  • 2
    The example is moving `init` to the `operator+` not to the `operator=`. – JHBonarius Sep 27 '20 at 12:08

1 Answers1

3

This is not a self-assignment.

A self-assignment would be init = std::move(init);, and you have init = std::move(init) + *first;.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • could you elaborate more on the differences in `init` object state between [self-assignment] and [not self-assignment containing self-move]. And I'll totally accept you answer – user2376997 Sep 27 '20 at 08:35
  • 2
    @user2376997 I'm not sure how to elaborate here. Overloaded `+` in general returns by value rather than a reference to its left operand. If it returns a reference to the left operand for your type, then yes, it would be a self-assignment. – HolyBlackCat Sep 27 '20 at 08:57