重载用户定义类型的全局交换
C++ 标准禁止在命名空间 std
中声明类型或定义任何内容,但它确实允许您为用户定义类型专门化标准 STL 模板。
通常,当我想为我自己的自定义模板类型专门化 std::swap
时,我只需这样做:
namespace std
{
template <class T>
void swap(MyType<T>& t1, MyType<T>& t2)
{
t1.swap(t2);
}
}
...并且效果很好。但我并不完全确定我通常的做法是否符合标准。我这样做正确吗?
The C++ standard prohibits declaring types or defining anything in namespace std
, but it does allow you to specialize standard STL templates for user-defined types.
Usually, when I want to specialize std::swap
for my own custom templated type, I just do:
namespace std
{
template <class T>
void swap(MyType<T>& t1, MyType<T>& t2)
{
t1.swap(t2);
}
}
...and that works out fine. But I'm not entirely sure if my usual practice is standard compliant. Am I doing this correctly?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
你所拥有的不是专业化,而是超载,这正是标准所禁止的。 (但是,它目前在实践中几乎总是有效,并且可能是您可以接受的。)
以下是您如何为类模板提供自己的交换:
这是您如何调用交换,您会注意到它在 Ex 中使用也交换:
相关:函数模板专业化的重要性和必要性
What you have is not a specialization, it is overloading and exactly what the standard prohibits. (However, it will almost always currently work in practice, and may be acceptable to you.)
Here is how you provide your own swap for your class template:
And here is how you call swap, which you'll notice is used in Ex's swap too:
Related: Function template specialization importance and necessity
为什么不在 MyType 的命名空间中定义交换并利用依赖于参数的查找功能?
Why won't you just define swap in MyType's namespace and exploit argument-dependent lookup power?
由于依赖于参数(又名 Koenig)查找,我相信您可以在所需类型的命名空间中指定您自己的交换,并且它将优先于
::std::swap
找到。另外,我相信::std::swap
的模板对于具有自己的交换成员函数的类会有不同的扩展,因此您可以将该成员函数添加到类中,并将其用于您的类型。Because of argument dependent (aka Koenig) lookup, I believe you can specify your own swap in the namespace of the type you want it for and it will be found in preference to
::std::swap
. Also, I believe the template for::std::swap
will expand differently for classes that have their own swap member function and so you can add that member function to the class and that will be used for your type.编辑
请参阅 Scott Meyer 的文章:请参阅Effective C++ 第三版,第 25 项:考虑支持非抛出交换 (p106-p112) 以确认我的答案。
最初的答案
斯科特·迈耶斯写过这个,所以我的答案来自记忆。
首先,在类的命名空间中定义一个交换函数。例如:
然后,如果可能(模板类 (*) 并不总是可能),在命名空间 std 中专门化交换函数。例如:
当使用交换函数时,间接执行此操作,将 std 交换函数导入到您的作用域中。例如:
一旦我可以访问我的书,我就会在此处发布确切的参考文献。
Edit
See Scott Meyer's article: See Effective C++ 3rd Edition, item 25: Consider support for a non-throwing swap (p106-p112) for a confirmation of my answer.
Original answer
Scott Meyers wrote about this, so my answer comes from memory.
First, define a swap function in the namespace of your class. For example :
Then, if possible (it is not always possible for templated classes (*) ), specialize the swap function in the namespace std. For example :
The, when using the swap function, do it indirectly, importing the std swap function into your scope. For example :
As soon as I have access to my books, I'll post here the exact reference.
您正在做的是重载而不是模板专业化。该标准不允许您在
namespace std
内重载 (17.6.4.2.1 §1)因此,最好将模板类型放入您自己的命名空间中,并在该命名空间内定义一个非成员
swap()
(这不是绝对必要的,但很好的做法)。这样,如果x
或y
在你的命名空间中。使用
swap()
的代码通常应使用using namespace std
技术。这样,ADL 就会找到您的交换版本,并且它会优先于std::swap()
函数,因为它更专业。What you're doing is an overload and not a template specialization. The standard does not allow you to overload inside
namespace std
(17.6.4.2.1 §1)Therefore, prefer to put your template type into your own namespace and define a non-member
swap()
within that namespace (this is not strictly necessary, but good practice). This wayswap(x,y)
will work from anywhere via argument dependent lookup (ADL, aka Koenig lookup), ifx
ory
are in your namespace.Code using
swap()
should normally use theusing namespace std
technique. This way your version of swap will be found by ADL and it will be prefered to thestd::swap()
function, since it is more specialized.在同一命名空间中定义您的类型和交换函数:
Define your type and your swap function in the same namespace:
定义自己的
交换
。此函数必须为除您的类型之外的任何类型 T 调用 std::swap 。Define own
swap
. This function must call std::swap for any type T except your types.