2013-04-27 89 views
2

如果我有一個函數模板可以爲所有類型Stream(例如,何時將模板參數類型約束爲具體的類

template<typename Stream> 
Stream& foo(Stream& stream) 
{ 
    return stream; 
} 

是否有限制類型爲具體類的任何優點,例如,

template<typename CharT, Traits> 
std::basic_istream<CharT, Traits>& foo(std::basic_istream<CharT, Traits>& stream) 
{ 
    return stream; 
} 

還是應該函數/類模板作爲一個經驗法則總是儘可能通用的,即使你有特定類型的想法?

+0

如果你的模板函數只能在文檔中的某些約束條件下工作。有人可能會提供一個類似istream的類,它可以在你的原始情況下工作,但不能在你的更明確的情況下工作。 – Zeta 2013-04-27 11:44:33

回答

2

我們沒有任何約束或概念但在當前的C++,所以你的舊模板界面比需要更多的一般,因爲它也接受未在其接口類型的流。當你調用你的函數模板並且它被重載時,這會造成容易模糊。

因此,儘可能使函數模板儘可能通用,但不是比需要的更一般。在這種情況下,你的努力是最好的。

+0

謝謝。如果我想創建一個既適用於左值又適用於右值的函數,除了將第一個簽名改爲「Stream &&」之外,還有其他選擇嗎?這對於泛型是否是有效的情況? – user657267 2013-04-27 12:06:30

+1

@ user657267你可以編寫一個'is_stream'特性類,然後採用'Stream &&'並使用SFINAE來強制執行'is_stream :: type> :: value'。 – Yakk 2013-04-27 12:31:57

+0

+1提到歧義。它可以通過'enable_if'使用SFINAE來避免,但是這不是很容易編寫(不提及閱讀,調試,維護和檢查;它只是沒有樂趣)。概念將幫助我們在將來的C++版本中,在那裏你可以限制模板類型。 – leemes 2013-04-30 08:28:07

1

超過限制型模板的好處是,你的函數工作,如果給定類型支持您的功能需要做的參數,沒有更多的東西。這也被稱爲「鴨子打字」。

這對於算術計算是非常好的,它然後自動適用於所有類型的算術運算符。

。另一方面,一個很好的例子,你不希望這是(即嚴格類型的優勢),當你想到它不能在「鴨打字」表達的類型的特定行爲,例如,如果你需要的功能來a += b是相同的a = a + b(雖然這應該一貫主張,如果你重載運算符),或一個特定的(並希望)呼籲類型的函數時的副作用發生。但是,例如(「T::size()預計會返回......的數量」),此類「要求」可以(並且通常)在您的功能的文檔(註釋)中表達。

一般的經驗法則是:如果你事先知道你要調用該函數,例如,如果你已經有了一個抽象的超類類型使用特定類型。如果您希望該類型的集合更「無限」,請使用模板。

相關問題