Is it okay to define a totally general swap() function?

  • unique_ptr<T> requires T* to be a NullablePointer [unique.ptr]p3
  • NullablePointer requires lvalues of T* to be Swappable [nullablepointer.requirements]p1
  • Swappable essentially requires using std::swap; swap(x, y); to select an overload for x, y being lvalues of type T* [swappable.requirements]p3

In the last step, your type foo::bar produces an ambiguity and therefore violates the requirements of unique_ptr. libstdc++’s implementation is conforming, although I’d say this is rather surprising.


The wording is of course a bit more convoluted, because it is generic.

[unique.ptr]p3

If the type remove_reference_t<D>::pointer exists,
then unique_ptr<T, D>::pointer shall be a synonym for
remove_reference_t<D>::pointer. Otherwise unique_ptr<T,
D>::pointer
shall be a synonym for T*. The type unique_ptr<T,
D>::pointer
shall satisfy the requirements of NullablePointer.

(emphasis mine)

[nullablepointer.requirements]p1

A NullablePointer type is a pointer-like type that supports null
values. A type P meets the requirements of NullablePointer if:

  • […]
  • lvalues of type P are swappable (17.6.3.2),
  • […]

[swappable.requirements]p2

An object t is swappable with an object u if and only if:

  • the expressions swap(t, u) and swap(u, t) are valid when evaluated in the context described below, and
  • […]

[swappable.requirements]p3

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 on a candidate set that includes:

  • the two swap function templates defined in <utility> and
  • the lookup set produced by argument-dependent lookup.

Note that for a pointer type T*, for purposes of ADL, the associated namespaces and classes are derived from the type T. Hence, foo::bar* has foo as an associated namespace. ADL for swap(x, y) where either x or y is a foo::bar* will therefore find foo::swap.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)