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が考慮されることを標準の文言で明言する
です.
その他の参照資料
- http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#225 - 上の問題に直接対応するStandard Library Defect Report
- http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#226 - swapとは逆に意図しないoverloadがADLで呼ばれてしまう問題.上のproposalで同時に解決される見込み
上の問題の別の解決の方向性として
- std名前空間に関数のoverloadを導入することを許す
- 関数テンプレートの部分特殊化を許す
の2点(正確にいうと関数テンプレートを部分特殊化が可能なクラステンプレートの静的関数へ委譲するという方法もあります.下のGotWのページ参照)が挙げられますがそれらに対する議論は以下です.
- http://www.gotw.ca/publications/mill17.htm - 関数のoverloadの追加は宣言順で呼ばれるものが変わるという微妙な振る舞いがあるので推奨されないか?
- http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2001/n1295.asc - 関数テンプレートに対して部分特殊化を導入する提案
not only for ::std::swap
以上はC++標準の swap という限定された対象ですが,一般に自由関数とADL,ユーザ側での自由関数のカスタマイズといったことが複合する場合の一つの指針として参考になるかと思います.