C++ 模板专门化与函数重载
我的一本教科书指出,您可以通过模板专门化或函数重载为标准库函数提供自己的实现,如C++ 模板专门化与函数重载,c++,stl,template-specialization,standard-library,overloading,C++,Stl,Template Specialization,Standard Library,Overloading,我的一本教科书指出,您可以通过模板专门化或函数重载为标准库函数提供自己的实现,如swap(x,y)。这对于任何可以从赋值交换以外的东西中获益的类型都是有用的,比如STL容器(我知道,它已经编写了交换) 我的问题如下: 更好的方法:模板专门化以提供专门的 交换实现,或函数重载提供精确的 您希望在没有模板的情况下使用的参数 为什么更好?或者如果他们是平等的,为什么会这样 短篇故事:可以的时候超负荷,需要的时候专业化 长篇故事:C++对专业化和超载的处理非常不同。最好用一个例子来解释这一点 tem
swap(x,y)
。这对于任何可以从赋值交换以外的东西中获益的类型都是有用的,比如STL容器(我知道,它已经编写了交换)
我的问题如下:
短篇故事:可以的时候超负荷,需要的时候专业化 长篇故事: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*);
模板void foo(T);
模板void foo(T*);//foo(T)过载
模板void foo(int*);//foo专业化(T*)
foo(新int);//调用foo(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*) !!!
模板void foo(T);
模板void foo(int*);//foo(T)专业化
模板void foo(T*);//foo(T)过载
foo(新int);//呼叫foo(T*)!!!
编译器甚至在查看专业化之前都会重载解析。因此,在这两种情况下,重载解析都选择foo(T*)
。然而,只有在第一种情况下,它才能找到foo(int*)
,因为在第二种情况下int*
专业化是foo(T)
的专业化,而不是foo(T*)
您提到了
std::swap
。这使得事情更加复杂
该标准规定,您可以向std
名称空间添加专门化。很好,所以你有一些Foo
类型,它有一个性能交换,然后你只需要在std
名称空间中专门使用swap(Foo&,Foo&)
。没问题
但是如果Foo
是一个模板类呢?C++没有函数的部分专门化,所以你不能专门研究<代码>交换< /C>。您唯一的选择是重载,但标准规定不允许将重载添加到std
命名空间中
此时,您有两个选项:
swap(Foo&,Foo&)
函数,并希望通过ADL找到它。我之所以说“希望”,是因为如果标准库调用swap,比如std::swap(a,b)代码>那么ADL就根本不起作用了
但是要记住的一点是,根本不能保证标准库使用
swap
。大多数算法都使用std::iter\u swap
,在我所研究的一些实现中,它并不总是使用std::swap
,短篇故事:可以过载时,需要时进行专门化
长篇故事: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*);
模板void foo(T);
模板void foo(T*);//foo(T)过载
模板void foo(int*);//foo专业化(T*)
foo(新int);//调用foo(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*) !!!
模板void foo(T);
模板void foo(int*);//foo(T)专业化
模板void foo(T*);//foo(T)过载
foo(新int);//呼叫foo(T*)!!!
编译器甚至在查看专业化之前都会重载解析。因此,在这两种情况下,重载解析都选择foo(T*)
。然而,只有在第一种情况下,它才能找到foo(int*)
,因为在第二种情况下int*
专业化是foo(T)
的专业化,而不是foo(T*)
您提到了
std::swap
。这使得事情更加复杂
该标准规定,您可以向std
名称空间添加专门化。很好,所以你有一些Foo
类型,它有一个性能交换,然后你只需要在std
名称空间中专门使用swap(Foo&,Foo&)
。没问题
但是如果Foo
是一个模板类呢?C++没有函数的部分专门化,所以你不能专门研究<代码>交换< /C>。您唯一的选择是重载,但标准规定不允许将重载添加到std
命名空间中
此时,您有两个选项:
swap(Foo&,Foo&)
函数,并希望通过ADL找到它。我之所以说“希望”,是因为如果标准库调用swap,比如std::swap(a,b)代码>那么ADL就根本不起作用了
但是要记住的一点是,根本不能保证标准库使用
swap
。大多数算法都使用std::iter\u swap
,在我所看到的一些实现中,它并不总是转发到std::swap
,不允许在std
命名空间中重载函数,但允许专门化模板(我记得),所以这是一个选项
另一个选项是将
swap
函数与其操作的对象放在同一名称空间中,并使用std::swap将函数放在同一名称空间中在调用非限定交换之前执行code>。不允许在std
命名空间中重载函数,但允许专门化模板(我记得),因此这是一个选项
另一个选项是将您的交换
函数