2013-02-27 265 views
7

這是非常迂腐但在C++ 03這顯然是不符合的程序超載(不專門)在std命名空間的模板函數:見這herelong discussion on comp.lang.c++.moderated重載(不專業)在std名字空間模板

即提到這是確定的:

namespace std 
{ 
    template <> 
    void swap (Foo & f, Foo & g) 
    { 
     // ... 
    } 
} 

但這不是(如果我理解正確的話...):

namespace std 
{ 
    template <typename T> 
    void swap (TempateFoo<T> & f, TempateFoo<T> & g) 
    { 
     // ... 
    } 
} 

這在C++ 11中仍然如此嗎?此外,這是否也適用於模板類(如std::hash),或者只是模板函數?

編輯:另外,有沒有任何標準庫實現的例子,使後者會在實踐中破壞事物?如果不是,像上面第二種情況一樣,是否有特定的原因來阻止超載? (什麼能在理論上可能會破壞?)

+0

我認爲你不能爲模板專業化以外的東西打開'std'命名空間。 – Nawaz 2013-02-27 05:26:27

+0

那麼第二個例子仍然是非法的? – 2013-02-27 05:27:32

+0

是的,但我**不是** 100%確定。 – Nawaz 2013-02-27 05:28:03

回答

7

不可能定義在C++函數模板的局部專業化,這樣你的第二示例定義過載專業化。由於標準只允許將專門化添加到名稱空間std,因此您的超載是非法的。

這在C++ 11中仍然如此嗎?

是的。

此外,這是否也適用於模板類(如std :: hash),或者只是模板函數?

無論如何你不能重載類模板,你只能重載函數。儘管同樣的規則適用,但如果專業化取決於用戶定義的(意爲非標準)類型,則只能專門化類模板。

是否存在不允許超載的特定原因,如上述第二種情況? (什麼能在理論上可能會破壞?)

作爲一個例子,實施可能要採取一個函數的地址,但是如果你重載函數然後取地址,可能會導致歧義和無法編譯,這意味着你剛剛在標準庫中打破了有效的代碼。

+0

好的,很好,最後一部分是有道理的。 – 2013-02-27 18:33:44

+0

是用戶自定義類型的部分特殊化(例如std :: hash),還是完全專業化? – 2013-02-27 18:49:36

+1

如果部分專業化取決於用戶定義的類型,那麼可以,例如, 'std :: hash >'是可以的,因爲它取決於'MyTemplate '這是一個用戶定義的類型 – 2013-02-28 12:15:28

6

n3376 17.6.4.2.1

C++程序的行爲,如果它增加了聲明或定義,空間std或未定義,空間std除非另有內 命名空間指定。只有當聲明取決於用戶定義類型 且專業化符合原始模板的標準庫要求並且不明確 禁止時,程序可以將任何標準庫模板的模板專用 添加到名稱空間標準。

17.6.4.2.2

C++程序的行爲,如果它聲明

未定義 - 一個標準庫類模板的任何成員函數的明確專業化,或

- 標準庫類或類模板的任何成員函數模板的明確專業化, 或

- 顯式或部分專業化標準庫類或類 模板的任何成員類模板。

程序可以顯式實例在標準庫中定義的模板,只有在聲明 依賴於用戶定義類型的名稱和實例化符合原始模板的標準庫要求 。

+0

偉大,謝謝!任何線索爲什麼不允許重載,但?它顯然已經充分討論了,所以我必須想象有一個限制的原因。 – 2013-02-27 05:37:36

+0

我現在已經接受了這個,但是如果任何人都可以跟隨這個限制的推理,那將是很棒的:)(我肯定有人肯定已經把這個提交給了委員會。) – 2013-02-27 05:52:33

+3

添加一個重載會導致現有的*無關*調用使用該過載而不是之前使用的任何內容。沒有關係,因爲根本沒有提到你的用戶定義類型。專業化無法做到這一點。 – 2013-02-27 06:15:35