簡體   English   中英

模板專業化 VS Function 重載

[英]Template Specialization VS Function Overloading

一本教科書我注意到您可以通過模板專業化或 function 重載為標准庫函數(如swap(x,y)提供自己的實現。 這對於任何可以從分配交換以外的東西中受益的類型都很有用,例如 STL 容器(我知道,它已經編寫了交換)。

我的問題如下:

  1. 更好的是:模板專業化為您提供專門的交換實現,或 function 重載提供您希望在沒有模板的情況下使用的確切參數?

  2. 為什么更好? 或者如果他們是平等的,這是為什么呢?

簡短的故事:在你可以的時候超負荷,在你需要的時候專注。

長話短說:C++ 以非常不同的方式對待特化和重載。 這最好用一個例子來解釋。

template <typename T> void foo(T);
template <typename T> void foo(T*); // overload of foo(T)
template <>           void foo<int>(int*); // specialisation of foo(T*)

foo(new int); // calls foo<int>(int*);

現在讓我們交換最后兩個。

template <typename T> void foo(T);
template <>           void foo<int*>(int*); // specialisation of foo(T)
template <typename T> void foo(T*); // overload of foo(T)

foo(new int); // calls foo(T*) !!!

編譯器甚至在查看特化之前就進行重載解析。 因此,在這兩種情況下,重載決議都選擇foo(T*) 然而,只有在第一種情況下它才會找到foo<int*>(int*)因為在第二種情況下int*foo(T) ,而不是foo(T*)


你提到了std::swap 這讓事情變得更加復雜。

該標准說您可以向std命名空間添加專業化。 太好了,所以你有一些Foo類型,它有一個高性能的交換,那么你只需在std命名空間中專門化swap(Foo&, Foo&) 沒問題。

但是如果Foo是一個模板類呢? C++ 沒有函數的部分特化,所以你不能特化swap 你唯一的選擇是重載,但標准說你不能在std命名空間中添加重載!

此時您有兩個選擇:

  1. 在您自己的命名空間中創建一個swap(Foo<T>&, Foo<T>&)函數,並希望通過 ADL 找到它。 我說“希望”是因為如果標准庫像std::swap(a, b);一樣調用 swap std::swap(a, b); 那么 ADL 根本就行不通。

  2. 忽略標准中說不要添加重載的部分,無論如何都要這樣做。 老實說,即使技術上不允許,但在所有現實場景中它都會起作用。

但要記住的一件事是,不能保證標准庫完全使用swap 大多數算法使用std::iter_swap ,在我看過的一些實現中,它並不總是轉發到std::swap

彼得亞歷山大的回答幾乎沒有什么可補充的。 讓我只提一個用途,其中函數專業化可能比重載更可取:如果您必須在沒有參數的函數中進行選擇

例如

template<class T> T zero();
template<> int zero() { return 0; }
template<> long zero() { return 0L; }

要使用函數重載做類似的事情,你必須在函數簽名中添加一個參數:

int zero(int) { return 0; }
long zero(long) { return 0L; }

不允許重載std命名空間中的函數,但允許專門化模板(我記得),所以這是一種選擇。

另一種選擇是將您的swap函數放在與其操作的事物相同的命名空間中並using std::swap; 在調用不合格的交換之前。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM