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

            Bug ID: 70530
           Summary: You should probably add addressof (a) != addressof (b)
                    check to std::swap
           Product: gcc
           Version: 6.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: safinaskar at mail dot ru
  Target Milestone: ---

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.

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.

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

Reply via email to