#include <type_traits>
struct E {
int x;
E( ) = default;
E(E&&) = delete;
E& operator=(E&&) = delete;
};
void swap(E& a, E& b) { /* Does NOT actually swap */ }
int main(){
static_assert( std::is_swappable_v<E> );
}
The above class E
is neither MoveConstructible
nor MoveAssignable
. Thus, the <utility>
library swap()
function cannot be used (C++17:23.2.3, paragraph 3). Instead, a local custom swap()
function is defined. However, it does not actually perform the swap operation.
In this context, the type trait std::is_swappable<>
(C++17:23.15.4.3) yields true. Nevertheless, the Swappable
requirements seem to be not fulfilled, looking at C++17:20.5.3.2, paragraph 2:
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
- these expressions have the following effects:
- the object referred to by t has the value originally held by u and
- the object referred to by u has the value originally held by t.
The expressions swap(e1,e2)
and swap(e2,e1)
are valid for two objects of type E
, but they don’t have the stated effects. Is the meaning of std::is_swappable<> not exactly the same as fulfilling the Swappable requirements? Or is the compiler (and the <type_traits>
library) trusting the user to implement the custom swap()
function with those stated effects?