https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70530

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |SUSPENDED
   Last reconfirmed|                            |2016-04-04
            Summary|You should probably add     |[DR2468] You should
                   |addressof (a) != addressof  |probably add addressof (a)
                   |(b) check to std::swap      |!= addressof (b) check to
                   |                            |std::swap
     Ever confirmed|0                           |1

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Askar Safin from comment #0)
> C++ standard says standard library functions may assume rvalue reference
> arguments are unique, i. e. are not aliased to any other arguments (final
> draft C++14 N3690 17.6.4.9). I think this implies that move assignment for
> standard classes assume there will be no move assignment to itself. Also, I
> think this is good idea for other classes to assume the same.

That rule is actually defective, see:

http://cplusplus.github.io/LWG/lwg-active.html#2468

> As well as I know there is no any mention in the standard that std::swap
> argument should not point to the same object. So, code "swap (a, a)" is
> legit. Moreover, this code can appear in real programs. For example, this is
> code from http://en.cppreference.com/w/cpp/algorithm/iter_swap (as on
> 2016-04-02):
> 
> // libstdc++'s general std::iter_swap just calls std::swap in c++11 mode
> template<class ForwardIt>
> void selection_sort(ForwardIt begin, ForwardIt end)
> {
>     for (ForwardIt i = begin; i != end; ++i)
>         std::iter_swap(i, std::min_element(i, end));
> }
> 
> Current libstdc++ implementation of std::swap calls move constructor (ctor)
> one time and move assignment (op=) two times. If we call std::swap (a, a),
> then there will be move op= to itself.
> 
> So, I think std::move should check whatever its arguments point to the same
> object.

That would not be conforming.

> It seems all standard classes will work correctly currently if we call
> std::swap (a, a) in stdlibc++. I. e. I cannot think about some concrete
> libstdc++ class where std::swap (a, a) will cause any damage. But still
> assuming rvalue reference is unique is good idea for other libraries, too.
> And this is possible that some library author will assume this and std::swap
> (a, a) will fail.
> 
> So, what to do? My proposed solution is to fix std::swap. But there are
> other variants, of course. For example, remove rvalue ref uniqueness
> assumption from the standard. Or add requirement for code which calls
> std::swap. Even if you decide to fix std::swap, I think it still be good
> idea to modify the standard. For example, to stay explicitly that a =
> std::move (a) is not allowed for standard classes, that this is recommended
> for other class to assume there will be no code "a = std::move (a)", that
> swap (a, a) is allowed and for this reason current libstdc++'s swap
> implementation is not allowed

The more likely direction is to require self-move (and therefore self-swap) to
be valid for all standard classes.

Reply via email to