http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60448
--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Looks like the difference between libc++ and libstdc++ is whether std::swap()
is declared before std::swap_ranges or not, this reproduces the same behaviour,
with swapper replacing swap_ranges:
namespace tagged
{
template <typename T>
struct Swappable {};
template <typename T>
void swap(Swappable<T> & a, Swappable<T> & b) {
static_cast<T &>(a).swap(static_cast<T &>(b));
}
} // namespace tagged
namespace std
{
template<typename T>
void do_std_swap(T& a, T& b)
{
T tmp = static_cast<T&&>(a);
a = static_cast<T&&>(b);
b = static_cast<T&&>(tmp);
}
#ifdef SWAP_FIRST
template<typename T>
void swap(T& a, T& b)
{
do_std_swap(a, b);
}
#endif
template<typename T>
void swapper(T t)
{
swap(*t, *t);
}
#ifndef SWAP_FIRST
template<typename T>
void swap(T& a, T& b)
{
do_std_swap(a, b);
}
#endif
}
int main()
{
struct local : tagged::Swappable<local> {
local(int x) : data(x) {}
local(local const &) = delete;
local(local &&) = delete;
local & operator=(local const &) = delete;
local & operator=(local &&) = delete;
void swap(local & other) {
auto x = other.data;
other.data = this->data;
this->data = x;
}
private:
int data;
};
local l{1};
std::swapper(&l);
}
When SWAP_FIRST is defined G++ and Clang call std::swap, otherwise they find
tagged::swap by ADL.