你应该在std命名空间中重载交换吗? [英] Should you overload swap in the std namespace?

查看:145
本文介绍了你应该在std命名空间中重载交换吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我今天读了一些有趣的话,说标准的方式调用swap的用户提供的类型(作为模板参数提供)是...

I read something interesting today that said the 'standard' way to call swap on a user provided type (provided as a template argument) is...

using std::swap;
swap(something, soemthingelse);

这样做的原因是使用参数依赖查找来使用 std 命名空间中的用户命名空间中的函数或 swap 这给我一个有趣的问题。当我为一个类重载 std :: swap 时,我实际上已经在 std 命名空间中定义它。 。 namespace std {void swap(/*...*/){/*...*/}} 。这种做法是否错误 ?我应该在 std 还是我自己的命名空间(以及为什么)中定义自己的 swap

The reason for this is to use argument dependent look-up to either use a swap function in a user namespace or swap in the std namespace. This raised an interested question for me. When I overload std::swap for one of my classes I had actually been defining it in the std namespace... namespace std { void swap(/*...*/){/*...*/} }. Is this practice wrong? Should I define my own swaps in std or my own namespace (and why)?

推荐答案

您错了:)


strong> 17.6.2.4.1 [namespace.std]



  1. 程序未定义,除非另有规定,如果它添加声明或定义到命名空间 std 或命名空间 std 只有声明依赖于用户定义的类型并且专业化满足原始库的标准库要求,程序才可以将任何标准库模板的模板专门化添加到命名空间 std 模板,并未明确禁止。

  1. The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.



您不能向命名空间 std 添加重载。您可以 > > 专门为您的类型,但如果您的类型是一个模板,您需要一个部分专业化 std :: swap< MyContainer< T>> 并且你不能部分地专门化一个函数模板,所以这不会工作,所以它不是一个好的方法。

That pretty clearly says you may not add overloads to namespace std. You could specialize std::swap<MyType> for your type, but if your type is a template you'd need a partial specialization, std::swap<MyContainer<T>> and you can't partially specialize a function template, so that won't work, so it's not a good approach in general.

C ++ 11也定义了可交换类型的要求,其中包括:

C++11 also defines the requirements for a type to be swappable which include:


17.6.3.2 [swappable.requirements]



  1. ...

  2. ...

  3. / code>和交换(u,t),应确保通过重载分辨率(13.3)选择名为swap的二进制非成员函数一个候选集,其中包含:

  1. ...
  2. ...
  3. The context in which swap(t, u) and swap(u, t) are evaluated shall ensure that a binary non-member function named "swap" is selected via overload resolution (13.3) on a candidate set that includes:





  • < utility> (20.2)和

  • 由参数相关查找>
  • the two swap function templates defined in <utility> (20.2) and
  • the lookup set produced by argument-dependent lookup (3.4.2).



c> swap 在两个可交换类型的对象上应该能够找到 std :: swap ,并且应该能够找到ADL的其他重载。调用它不合格(没有明确的模板参数列表)确保ADL发生并包括< utility> 并添加 std的using- :swap 确保可以找到标准重载。

So calling swap on two objects of swappable type should be able to find std::swap and should be able to find other overloads by ADL. Calling it unqualified (and without an explicit template argument list) ensures ADL happens, and including <utility> and adding the using-declaration for std::swap ensures the standard overloads can be found. So doing it the way you show in your question meets those requirements.

这很清楚地定义了在所使用的意义上是什么需要可交换通过标准,这是标准库所需要的< algorithm> 中的函数。

That pretty clearly defines what it takes to be swappable in the sense used by the standard, which is what is required by the standard library e.g. by the functions in <algorithm>.

如果你把 swap 重载你的类型的类型的命名空间,然后他们可以找到ADL。这是正确的事情,无论如何,与您的类型相关的功能属于与您的类型相同的命名空间,请参阅项目57在 C ++编码标准,Sutter和Alexandrescu有关该主题的更多细节。

If you put swap overloads for your type in your type's namespace then they can be found by ADL. That is the right thing to do anyway, functions related to your type belong in the same namespace as your type, see Item 57 in C++ Coding Standards by Sutter and Alexandrescu for more details on that topic.

简而言之,你一直做错了。你读的是正确的。使用std :: swap 并依靠ADL始终有效(对于模板和非模板),并避免未定义的行为。 Yay。

So in short, you have been doing it wrong. What you read is correct. Doing using std::swap and relying on ADL always works (for templates and non-templates) and avoids undefined behaviour. Yay.

N.B。 C ++ 03标准并不清楚如何交换用户定义的类型。有关此领域的一些历史记录,请参阅 N1691 2.2 ,其中定义了自定义点,并显示在API中定义它们的不同方法。在C ++ 11中用于交换类型的协议使用这些方法之一,并且现在清楚和明确地祝福为正确的方式为您的类型提供交换功能。其他库中的其他定制点可以使用其他方法,但是在C ++ 11中可交换意味着使用std :: swap; 并依靠ADL。

N.B. The C++03 standard was less clear about how user-defined types should be swapped. For some history around this area see N1691 2.2 which defines the term customization point and shows different ways to define them in APIs. The protocol used in C++11 for swapping types uses one of those ways, and is now clearly and unambiguously blessed as the "correct way" to provide a swap function for your type. Other customization points in other libraries can use other approaches, but to be swappable in C++11 terms means using std::swap; and relying on ADL.

这篇关于你应该在std命名空间中重载交换吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆