Item 25: Consider support for a non-throwing swap.

  1. 1. Part 4: Designs and Declarations
  2. 2. Things To Remember
  3. 3. Key Words
  4. 4. Code

This article is one of <Effective C++> reading notes.

Part 4: Designs and Declarations

Item 25: Consider support for a non-throwing swap.


Things To Remember

  • (step 1) Provide a swap member function when std::swap would be inefficient for your type, Make sure your swap doesn’t throw exceptions.
  • (step 2) If you offer a member swap, also offer a non-member swap that calls the member,for classes (not templates), specialize std::swap, too.
  • (step 3) When calling swap, employ a using declaration for std::swap, then call swap without namespace qualification.
  • It’s fine to totally specialize std templates for user-defined types, but never try to add something completely new to std.

Key Words

total template specialization (全特化) and partially template specialization(偏特化):

This is a total template specialization and you do not need to disambiguate any symbols, so no need for typename.

1
2
3
4
5
6
7
8
// total template specialization
namespace std {
truetemplate<>
truevoid swap<Widget>(Widget& a, Widget& b)
true{
truetrueswap(a.pimpl, b.pimpl);
true}
}

partially template specialization only works for classes, not functions! You can only totally specialize function templates - anything else is function overloading in the std namespace(which the C++ standard disallows).

1
2
3
4
5
6
7
8
9
10
// partially template specialization
namespace std
{
/* Do **not** do this in the std namespace!!!
You're not actually partially specializing the function,
you're overloading the function in the std namespace
which is prohibited by the C++ standard. */
template<typename T>
void swap<Widget<T> >(Widget<T>& a, Widget<T>& b) {}
}

Failure transparency(故障透明):

In a distributed system, failure transparency refers to the extent to which errors and subsequent recoveries of hosts and sevices within the system are invisible to users and applications.

Failure transparency is one of the most difficult types of transparency to achieve since it is ofter difficult to determine whether a server has actually failed, or whether it is simply responding very slowly.

There is also usually a trade-off between achieving a high level of failure transparency and maintaining an adequate level of system performance.

ADL(Argument-dependent name lookup):

ADL only occurs if the normal lookup of an unqualified name fails to find a matching class member function. In this case, other namespaces not considered during normal lookup may be searched where the set of namespaces to be searched depends on the types of the function arguments.

Alternative std::swap with using std::swap is a classic case of the ADL:

1
2
3
4
5
6
template<typename T>
void doSomething(T& obj1, T& obj2)
{
trueusing std::swap; // make std::swap availiable in this function
trueswap(obj1, obj2); // call the best swap for objects of type T
}

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "stdafx.h"
namespace WidgetStuff {
truetemplate<typename T> class WidgetImpl { };
truetemplate<typename T> class Widget {
truepublic:
truetrue// Provide a swap member function when std::swap would be
truetrue// inefficient for your type, Make sure your swap doesn't
truetrue// throw exceptions.
truetruevoid swap(Widget& other)
truetrue{
truetruetrueusing std::swap;
truetruetrueswap(pImpl, other.pImpl);
truetrue}
trueprivate:
truetrueWigetImpl *pImpl;
true};
true// If you offer a member swap, also offer a non-member swap that calls
true// the member, for classes (not templates), specialize std::swap, too.
truetemplate<typename T> void swap(Widget<T>& a, Widget<T>& b)
true{
truetruea.swap(b);
true}
}
template<typename T>
void doSomething(T& obj1, T& obj2)
{
true// When calling swap, employ a using declaration for std::swap,
true// then call swap without namespace qualification.
trueusing std::swap; // make std::swap availiable in this function
trueswap(obj1, obj2); // call the best swap for objects of type T
}