你就錯了:)
17.6.2.4.1 [namespace.std]
- 一個C的行爲++程序是不確定的,如果它增加了聲明或者,除非另有規定定義,命名空間
std
或命名空間的命名空間std
內。程序可以添加一個模板專業化爲任何標準庫模板命名空間std
只有在聲明依賴於用戶定義類型和專業化符合原始模板的標準庫要求,並沒有明確禁止。
這很清楚地說,你可以不添加過載到命名空間std
。您可以專門爲std::swap<MyType>
你的類型,但如果你的類型是一個模板,你需要一個局部特殊化,std::swap<MyContainer<T>>
你不能偏特函數模板,所以這是行不通的,所以它不是一個好方法一般來說。
C++ 11還定義一類的要求是可交換其中包括:
17.6.3.2 [swappable.requirements]
- ...
- ...
- 上下文中
swap(t, u)
和swap(u, t)
被評估應確保通過重載解析(13.3)上的候選集合,其中包括選擇命名爲「交換」的二進制非成員函數:
- 中定義的兩個交換函數模板
<utility>
(20.2)和
- 通過參數相關的查找(3.4.2)中產生的查找集。
因此呼籲swap
兩個熱插拔類型的對象應該能夠找到std::swap
,應該能夠通過ADL找到其他重載。調用它不合格(和沒有明確的模板參數列表)保證ADL發生,包括<utility>
並添加使用聲明爲std::swap
確保標準的重載可以找到。因此,按照您在問題中展示的方式來滿足這些要求。
這很清楚地定義了標準庫所要求的標準所使用的意義上的可交換的含義,例如,通過<algorithm>
中的函數。
如果你把swap
重載到你的類型的命名空間中,那麼它們可以被ADL找到。無論如何,這是正確的做法,與您的類型相關的函數與您的類型屬於相同的名稱空間,請參閱Sutter和Alexandrescu的中的Item 57以瞭解有關該主題的更多詳細信息。
總之,你一直在做錯了。你讀的是正確的。做using std::swap
和依靠ADL總是工作(模板和非模板),並避免未定義的行爲。好極了。
N.B. C++ 03標準對用戶定義的類型應該如何交換不太清楚。有關此區域的一些歷史記錄,請參閱N1691 2.2,其中定義了術語定製點並顯示了在API中定義它們的不同方法。 C++ 11中用於交換類型的協議使用這些方法之一,現在明確而明確地祝福您爲您的類型提供交換功能的「正確方法」。其他庫中的其他自定義點可以使用其他方法,但可以使用C++ 11進行交換,這意味着可以使用using std::swap;
並依賴於ADL。
我想你總是可以做一個明確的專業化,它是*允許的...... –
@KerrekSB仍然問題在於是否應該禁止專業化,以支持啓用ADL的自有名稱空間函數。 –
如果你們倆都這樣做,你們難道不明白嗎? –