您是否应该更喜欢重载而不是函数模板的专门化?

2023-12-25

我的一本教科书指出,您可以为标准库函数提供自己的实现,例如swap(x,y)通过模板专门化或函数重载。这对于任何可以从赋值交换以外的东西中受益的类型都很有用,例如 STL 容器(我知道,它已经编写了交换)。

我的问题如下:

  1. 更好的是:模板专业化为您提供专业化 交换实现或函数重载提供了确切的 您希望在没有模板的情况下使用参数?

  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), not foo(T*).


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

该标准规定您可以将专业化添加到std命名空间。太好了,所以你有一些Foo类型并且它有一个高性能交换然后你只需专门化swap(Foo&, Foo&) in the std命名空间。没问题。

但如果Foo是模板类吗? C++ 没有函数的部分特化,所以你不能特化swap。您唯一的选择是重载,但标准规定您不允许将重载添加到std命名空间!

此时您有两个选择:

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

  2. 忽略标准中规定不要添加重载的部分,无论如何都要这样做。老实说,尽管技术上不允许,但在所有现实场景中它都会起作用。

但要记住的一件事是,不能保证标准库使用swap根本不。大多数算法使用std::iter_swap在我看过的一些实现中,它并不总是转发std::swap.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

您是否应该更喜欢重载而不是函数模板的专门化? 的相关文章

随机推荐