その swap 操作に対して、総称プログラミングを有効活用できるよう統一されたインタフェースを提供する。
swap の典型的な実装は次のようになる。
void swap (T &a, T &b)
{
  T temp (a);
  a = b;
  b = temp;
}
同じ型の大きく複雑なオブジェクトの swap は、中間的な一時オブジェクトのためのリソースの獲得と解放により、
非常に非効率になりうる。
また、前述の swap の実装では、リソースが利用可能ではなかった場合、例外が送出されるかもしれない。
そもそも新しいリソースの要求が必要でなかった場合には、そのような挙動は認めがたい。
throw しない swap イディオム(Non-throwing swap idiom)は、望ましい効果を得るためにハンドル・ボディ(Handle Body)イディオムを使用する。
対象の概念は、2つの実装クラスに分割される。
一つは、ハンドル(handle)であり、もう一つはボディ(body、本体)である。
ハンドルはボディ(本体)オブジェクトへのポインタを保持する。
swap は、単純なポインタの交換として実装される。
例外を送出しないことが保証され、新しいリソースが獲得も解放もされないため非常に効率的である。
namespace Orange {
class String 
{
    char * str;
  public:
    void swap (String &s) throw ()
    {
      std::swap (this->str, s.str);
    }
};
}
効率的で例外安全な swap 関数は、(上述のように)メンバ関数として実装可能だが、
throw しない swap イディオムは、単純さ、整合性、そして総称プログラミングの有効活用のために
その先を行く。
std::swap の明示的特殊化を、クラス自身の名前空間だけでなく std 名前空間にも追加すべきである。
namespace Orange { // String の名前空間
  void swap (String & s1, String & s2) throw ()
  {
    s1.swap (s2);
  }
}
namespace std {
  template <>
  void swap (Orange::String & s1, Orange::String & s2) throw ()
  {
    s1.swap (s2);
  }
}
これら 2 箇所への追加は、swap の 2 つの異なる一般的な使用法に対応する。
1 つは、被修飾の swap であり、もう一つは完全修飾の swap (例えば std::swap)である。
非修飾の swap が使用される時には、正しい swap が Koenig の名前探索により(既に定義済みのものから)発見される。
完全修飾の swap が使用される時には、Koenig の名前探索は抑止され、
std 名前空間内のものが代わりに使用される。
これはよく知られた挙動である。
残りの議論では、完全修飾の swap のみを用いる。
C++ プログラマはしばしば下記のように swap 関数を慣用的に std:: で完全修飾して呼び出すため、統一された見た目と印象を与える。
template 
void zoo (T t1, T t2) {
//...
int i1, i2;
std::swap(i1,i2); // 統一性に注目
std::swap(t1,t2); // 同上
}
そのような場合、zoo が先に定義した String によってインスタンス化されたときに、正しい効率的な swap の実装が選択される。
さもなくば、
メンバ関数の swap と、名前空間での swap 関数を定義した目的を完全に無にして
デフォルトの std::swap 関数テンプレートがインスタンス化されるだろう。
swap の明示的特殊化を std 名前空間に定義するというこのイディオムは、特に総称プログラミングで有用である。
throw しない swap イディオムの使用による統一性は、下記の例のような再帰的な利用をもたらす。
class UserDefined 
{
    String str;
  public:
    void swap (UserDefined & u) throw () 
    { 
      std::swap (str, u.str); 
    }
};
namespace std
{
  // std 名前空間のテンプレートの完全特殊化は、std 名前空間に追加できる
  template <>
  void swap (UserDefined & u1, UserDefined & u2) throw ()
  {
    u1.swap (u2);
  }
}
class Myclass
{
    UserDefined u;
    char * name;
  public:
    void swap (Myclass & m) throw ()
    {
      std::swap (u, m.u);       // 統一性によるイディオムの再帰的な使用
      std::swap (name, m.name); // 同上
    }   
}
namespace std
{
  // std 名前空間のテンプレートの完全特殊化は、std 名前空間に追加できる
   template <> 
   void swap (Myclass & m1, Myclass & m2) throw ()
   {
     m1.swap (m2);
   }
};
従って、例外安全で効率的な swap の実装に従った、その型の std::swap の特殊化を定義するのは良い考えである。
現在の C++ 標準は、新しいテンプレートを std 名前空間に追加することを認めていないが、std 名前空間のテンプレートを特殊化して std 名前空間に置くことは認めている。
テンプレートクラス(例：Matrix)に対して throw しない swap イディオムを使用することは微妙な問題になりうる。
C++98 標準では、ユーザ定義型に対しては std::swap の完全特殊化のみ std 名前空間に定義することを認めている。
部分特殊化や、関数オーバーロードは認められていない。
テンプレートクラス(例：Matrix)に対して同様の効果を得ようとする試みは、std 名前空間での std::swap のオーバーロードに帰着するが、これは規格的には未定義動作となる。
compl.lang.c++.moderated ニュースグループ
の壮大で長大な議論のスレッド
http://groups.google.ca/group/comp.lang.c++.moderated/browse_thread/thread/b396fedad7dcdc81 Namespace issues with specialized swap
で指摘している人々がいるように、
これは必ずしも理想の状態ではない。
解法は、クラスが定義されている名前空間と同じ名前空間内にオーバーロードされた swap 関数テンプレートを定義するか、
何も起こらないことを期待して未定義動作を無視するか、
次期標準での修正を待つかである。
Boost のスマートポインタの全て (例 boost::shared_ptr)
More C++ Idioms/Non-throwing swap
|THROWしないSWAP]]