我应该专门化或重载在诸如"std::swap"之类的命名空间中定义的模板吗

Should I specialize or overload templates defined in a namespace like `std::swap`?

本文关键字:quot 命名空间 定义 std 重载 专门化 我应该 swap      更新时间:2024-05-21

如果我有一些管理资源的类类型,并且我的类需要定义一个swap()函数作为其接口的一部分,该接口可以在该类型的对象上工作,那么我通常会这样做:

struct Foo{};
Foo f1, f2;
void swap(Foo& lhs, Foo& rhs){
// code to swap member data of lhs and rhs
}
int main(){
using std::swap;
Foo f1, f2;
swap(f1, f2);
}
  • 现在,我是重载std::swap,还是专门化它?

  • 我已经了解到,如果我想专门化标准库的函数/类模板,那么我应该打开名称空间std并在那里声明专门化。例如:

namespace std{
void swap(Foo&, Foo&);
}
  • 我记得,当为我打算用作无序关联容器(如std::unordered_map(的元素类型的类型专门化std::hash时,我确实以这种方式专门化了std::hash
namespace std{ // opening namespace std
template<>
class hash<Foo>{
//...
};
}

那么,这是正确的吗?我应该重载还是专用std::swap

该标准通常不允许在命名空间std:中添加重载或专业化

[namespace.std]/1除非另有说明,否则如果C++程序向命名空间std或命名空间std中的命名空间添加声明或定义,则其行为是未定义的。

专门化类模板有一个例外。您的std::hash<Foo>示例属于以下类别:

[namespace.std]/2除非明确禁止,否则程序可以将任何标准库类模板的模板专用化添加到命名空间std,前提是(a(添加的声明取决于至少一个程序定义的类型,并且(b(专用化满足原始模板的标准库要求。

您可以在命名空间std外重载某些标准库函数,并依赖ADL来找到它们:

[namespace.std]/7除了在命名空间std或命名空间std内的命名空间中,程序可以为指定为自定义点的任何库函数模板提供重载,前提是(a(重载的声明取决于至少一个用户定义的类型,并且(b(重载满足定制点的标准库要求。[注意:这允许对自定义点进行(限定或非限定(调用,为给定的参数调用最合适的重载。--end Note]

std::swap实际上是一个自定义点。