title: Why can std::swap correctly swap custom objects?
body: <p>I've written the following code as an example of a correct implementation of a <code>swap</code> function in c++.</p>
  
  <pre><code>#include &lt;iostream&gt;
  
  class Complex
  {
      int a;
      int b;
      friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp;, const Complex&amp;);
      friend void swap(Complex&amp; rhs, Complex&amp; lhs) noexcept;
  public:
      Complex(): a(0), b(0) {};
      Complex(int a, int b): a(a), b(b) {};
  };
  
  void swap(Complex&amp; rhs, Complex&amp; lhs) noexcept
  {
      using std::swap;
      swap(rhs.a, lhs.a);
      swap(rhs.b, lhs.b);
  }
  
  std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const Complex&amp; c)
  {
      os &lt;&lt; c.a &lt;&lt; c.b;
      return os;
  }
  
  class Swapable
  {
      int a;
      int b;
      Complex complex;
      friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp;, const Swapable&amp;);
      friend void swap(Swapable&amp;, Swapable&amp;) noexcept;
  public:
      Swapable(): a(0), b(0) {};
      Swapable(int a, int b): a(a), b(b), complex(a+1, b+1) {};
  };
  
  void swap(Swapable&amp; rhs, Swapable&amp; lhs) noexcept
  {
      std::cout &lt;&lt; "Swapping" &lt;&lt; std::endl;
      using std::swap;
      swap(rhs.a, lhs.a);
      swap(rhs.b, lhs.b);
      swap(rhs.complex, lhs.complex);
  }
  
  std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const Swapable&amp; s)
  {
      os &lt;&lt; s.a &lt;&lt; s.b &lt;&lt; s.complex;
      return os;
  }
  
  int main()
  {
      Swapable s_1(1,1);
      Swapable s_2(2,2);
  
      std::cout &lt;&lt; "Before swap" &lt;&lt; std::endl;
      std::cout &lt;&lt; s_1 &lt;&lt; std::endl;
      std::cout &lt;&lt; s_2 &lt;&lt; std::endl;
  
      swap(s_1, s_2);
  
      std::cout &lt;&lt; "After swap" &lt;&lt; std::endl;
      std::cout &lt;&lt; s_1 &lt;&lt; std::endl;
      std::cout &lt;&lt; s_2 &lt;&lt; std::endl;
  
      std::swap(s_1, s_2); // It should fail. Shouldn't it?
  
      std::cout &lt;&lt; "Second swap" &lt;&lt; std::endl;
      std::cout &lt;&lt; s_1 &lt;&lt; std::endl;
      std::cout &lt;&lt; s_2 &lt;&lt; std::endl;
  }
  </code></pre>
  
  <p>The output is :</p>
  
  <pre><code>Before swap
  1122
  2233
  Swapping
  After swap
  2233
  1122
  Second swap
  1122
  2233
  </code></pre>
  
  <p>Every thing works as expected when I call the unqualified <code>swap</code>. However, I was expecting a compile error when I call the <code>std::swap</code> with my custom object. Why is the <code>std::swap</code> function able to swap correctly my custom object?</p>