swapについて

swapについて自分が考え・まとめていた問題があったんですが,以下のドキュメントがうまいことまとめてくれていました.
http://www.octopull.demon.co.uk/c++/dragons/index.html#box2
ただ,このドキュメントにおける標準委員会の方向性についての部分,

3. In a recent resolution of an issue the standards committee has indicated that where one standard function/template function is required to be used by another then the use should be fully qualified (i.e. std::swap(t1, t2);) to prevent the application of Koenig Lookup. If you (or I) provide yournamespace::swap() the standard algorithms won't use it.

は現在は状況が変わっています.標準委員会は以下のproposal
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1523.htm
を受け入れるという方針になっています.このproposalの要点は要するに

  • 標準のアルゴリズム内で他の標準の自由関数を呼ぶときは基本的に ::std::swap などとfull-qualifiedで呼ぶ
  • いくつかのアルゴリズム内では自由関数をunqualifiedで呼び出すことによって,ADLによって導入されるユーザ定義型に対するoverloadを受け入れる.(例えばsortの内部におけるswapとか)ただし,この場合にはADLによるswapのoverloadが考慮されることを標準の文言で明言する

です.

その他の参照資料

上の問題の別の解決の方向性として

  1. std名前空間に関数のoverloadを導入することを許す
  2. 関数テンプレートの部分特殊化を許す

の2点(正確にいうと関数テンプレートを部分特殊化が可能なクラステンプレートの静的関数へ委譲するという方法もあります.下のGotWのページ参照)が挙げられますがそれらに対する議論は以下です.

not only for ::std::swap

以上はC++標準の swap という限定された対象ですが,一般に自由関数とADL,ユーザ側での自由関数のカスタマイズといったことが複合する場合の一つの指針として参考になるかと思います.

ライブラリ内における自由関数呼び出しの指針
  • ユーザの特殊化を前提とした関数を呼び出す場合 - 名前空間の修飾無しで呼び出す.(他の名前空間にある自由関数をADLの効かないPODなどに対しても呼び出したい場合はusingと併用する)ただし,これは暗黙のうちにユーザの名前空間を汚していることになるので,ドキュメントで明確に言及しなければならない
  • ユーザの特殊化を前提としない関数を呼び出す場合 - 名前空間の修飾をつけて呼び出す