あなたはそれを間違っています:)
17.6.2.4.1 [名前空間.std]
- 特に指定がない限り、名前空間
std
または名前空間内の名前空間に宣言または定義を追加する場合、C++ プログラムの動作は未定義です。プログラムは、宣言がユーザー定義型に依存し、特殊化が元のテンプレートの標準ライブラリ要件を満たし、明示的に禁止されていない場合にのみ、std
標準ライブラリ テンプレートのテンプレート特殊化を名前空間に追加できます。std
これは、 namespace にオーバーロードを追加できないことを明確に示していますstd
。型を特殊化することはできstd::swap<MyType>
ますが、型がテンプレートの場合は部分的な特殊化が必要でありstd::swap<MyContainer<T>>
、関数テンプレートを部分的に特殊化することはできないため、それは機能しないため、一般的には良いアプローチではありません.
C++11 では、型をスワップ可能にするための要件も定義されています。
17.6.3.2 [swappable.requirements]
- ...
- ...
swap(t, u)
とが評価されるコンテキストでは、swap(u, t)
「swap」という名前のバイナリ非メンバー関数が、以下を含む候補セットのオーバーロード解決 (13.3) を介して選択されることが保証されます。
<utility>
(20.2) で定義された 2 つの swap 関数テンプレートと
- 引数依存ルックアップ (3.4.2) によって生成されたルックアップ セット。
swap
そのため、スワップ可能な型の 2 つのオブジェクトを呼び出すとstd::swap
、ADL によって他のオーバーロードを見つけることができ、他のオーバーロードを見つけることができるはずです。それを非修飾で (明示的なテンプレート引数リストなしで) 呼び出すと、ADL が確実に発生<utility>
し、using-declaration for を含めて追加するとstd::swap
、標準のオーバーロードが確実に見つかります。したがって、質問で示した方法でそれを行うと、これらの要件が満たされます。
これは、標準で使用される意味でスワップ可能であるために必要なものを明確に定義しています。これは、標準ライブラリで必要とされるものです<algorithm>
。
swap
型の名前空間に型のオーバーロードを配置すると、それらは ADL によって検出されます。いずれにせよ、それは正しいことです。型に関連する関数は、型と同じ名前空間に属します。そのトピックの詳細については、Sutter と Alexandrescu によるC++ コーディング標準の項目 57 を参照してください。
要するに、あなたはそれを間違ってやっています。あなたが読んだことは正しいです。ADLの実行using std::swap
と依存は常に機能し (テンプレートと非テンプレートの場合)、未定義の動作を回避します。わーい。
注: C++03 標準では、ユーザー定義型をどのように交換するかについてあまり明確ではありませんでした。この分野の歴史については、 N1691 2.2を参照してください。これは、カスタマイズ ポイントという用語を定義し、API でそれらを定義するさまざまな方法を示しています。型を交換するために C++11 で使用されているプロトコルは、これらの方法の 1 つを使用しており、型にスワップ関数を提供する「正しい方法」として明確かつ明確に祝福されています。他のライブラリの他のカスタマイズ ポイントは他のアプローチを使用できますが、C++11 用語で交換可能であるということはusing std::swap;
、ADL に依存することを意味します。