繁体   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