没有什么可以补充彼得·亚历山大的答案。让我只说一说,如果必须从没有参数的函数中选择
一本教科书,我注意到您可以通过模板专用化或函数重载为swap(x,y)
等标准库函数提供自己的实现。对于任何可以受益于分配交换以外的东西的类型,这都是很有用的,例如STL containers
(我已经知道已经写了交换)。
我的问题如下:
更好:模板专门化为您提供专门的交换实现或函数重载,以提供确切的信息您希望在没有模板的情况下使用的参数?
为什么更好?或者,如果它们相等,为什么会这样?
短篇小说:在可能的情况下超负荷,在需要时进行专业化。
长话短说: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
类型,并且具有性能交换,那么您只需在swap(Foo&, Foo&)
名称空间中专门设置std
。没问题。
但是如果Foo
是模板类怎么办? C ++的功能没有部分专业化,因此您不能专业化swap
。唯一的选择是重载,但是标准说不允许您将重载添加到std
名称空间中!
您目前有两个选择:
在您自己的名称空间中创建swap(Foo<T>&, Foo<T>&)
函数,并希望可以通过ADL找到它。我之所以说“希望”,是因为如果标准库像std::swap(a, b);
那样调用swap,那么ADL就根本无法工作。
忽略标准部分,即不要添加重载,还是要这样做。老实说,即使从技术上讲它是不允许的,但在所有现实情况下它都可以工作。
不过要记住的一件事是,不能保证标准库完全使用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;
放置在同一命名空间中。
没有什么可以补充彼得·亚历山大的答案。让我只说一说,如果必须从没有参数的函数中选择
不允许您在std
名称空间中重载函数,但是允许您对模板进行专门化(正如我所记得的,所以这是一种选择。