Here is a possible definition of std::swap
:
template<class T>
void swap(T& a, T& b) {
T tmp(std::move(a));
a = std::move(b);
b = std::move(tmp);
}
I believe that
std::swap(v,v)
is guaranteed to have no effects andstd::swap
can be implemented as above.
The following quote seems to me to imply that these beliefs are contradictory.
17.6.4.9 Function arguments [res.on.arguments]
1 Each of the following applies to all arguments to functions defined in the C++ standard library, unless explicitly stated otherwise.
...
- If a function argument binds to an rvalue reference parameter, the implementation may assume that this parameter is a unique reference to this argument. [ Note: If the parameter is a generic parameter of the form T&& and an lvalue of type A is bound, the argument binds to an lvalue reference (14.8.2.1) and thus is not covered by the previous sentence. — end note ] [ Note: If a program casts an lvalue to an xvalue while passing that lvalue to a library function (e.g. by calling the function with the argument move(x)), the program is effectively asking that function to treat that lvalue as a temporary. The implementation is free to optimize away aliasing checks which might be needed if the argument was an lvalue. —endnote]
(thanks to Howard Hinnant for providing the quote)
Let v
be an object of some movable type taken from the Standard Template Library and consider the call std::swap(v, v)
. In the line a = std::move(b);
above, it is the case inside T::operator=(T&& t)
that this == &b
, so the parameter is not a unique reference. That is a violation of the requirement made above, so the line a = std::move(b)
invokes undefined behavior when called from std::swap(v, v)
.
What is the explanation here?