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.

Reply via email to