模板专精VSfunction重载

一本教科书我注意到,你可以提供自己的实现标准库函数,如swap(x,y)通过模板专门化function重载。 这对任何可以从除了赋值交换以外的其他types都有用的types是有用的,比如STL containers (已经有了交换,我知道)。

我的问题是:

  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*) !!! 

编译器甚至在重视专业化之前做了重载parsing。 所以,在这两种情况下,重载分辨率都selectfoo(T*) 。 但是,只有在第一种情况下才会findfoo<int*>(int*)因为在第二种情况下, int*foo(T) ,而不是foo(T*)


你提到了std::swap 。 这使事情变得更加复杂。

该标准说,你可以添加特化到std命名空间。 太好了,所以你有一些Footypes,它有一个高性能的交换,那么你只需要在std命名空间中专门swap(Foo&, Foo&) 。 没问题。

但是,如果Foo是一个模板类呢? C ++没有部分function的专业化,所以你不能专注于swap 。 你唯一的select是重载,但是标准说你不允许在std命名空间中添加重载。

在这一点上你有两个select:

  1. 在你自己的命名空间中创build一个swap(Foo<T>&, Foo<T>&)函数,并希望通过ADLfind它。 我说“希望”,因为如果标准库调用交换像std::swap(a, b); 那么ADL根本行不通。

  2. 忽略标准中说不要添加重载的部分,并且无论如何都要这样做。 老实说,即使在技术上是不允许的,在所有现实的情况下,它都会起作用。

要记住的一件事是,不能保证标准库完全使用swap 。 大多数algorithm使用std::iter_swap ,在我看过的一些实现中,它并不总是转发到std::swap

彼得·亚历山大的答案几乎没有增加。 让我仅仅提到一个使用这个特殊function的应用程序可能比overloading更好:如果你必须在没有参数的函数中进行select

例如

 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命名空间中重载函数,但是你可以专门化模板(我记得),所以这是一个选项。

另一个select是把你的swap函数放在和它一样的命名空间中,并using std::swap; 在调用不合格的交换之前。