While implementing a custom tuple
(here), I found there is a wired swap()
function that takes const
parameters (cppreference):
template< class... Types >
constexpr void swap( const std::tuple<Types...>& lhs,
const std::tuple<Types...>& rhs ) noexcept(/* see below */);
and a const-qualified swap()
member function (cppreference):
constexpr void swap( const tuple& other ) noexcept(/* see below */) const;
const
means the object is read-only, but to swap two objects, it has to modify the objects, which violates the const
-ness.
So, What's the purpose of const swap() function?
This was introduced in the "zip" proposal P2321 originally described in "A Plan for C++23 Ranges" P2214.
P2321
swap for const tuple and const pair. Once tuples of references are made const-assignable, the default std::swap can be called for const tuples of references. However, that triple-move swap does the wrong thing:
int i = 1, j = 2; const auto t1 = std::tie(i), t2 = std::tie(j); // If std::swap(t1, t2); called the default triple-move std::swap then // this would do auto tmp = std::move(t1); t1 = std::move(t2); t2 = std::move(tmp); // i == 2, j == 2
This paper therefore proposes adding overloads of swap for const tuples and pairs to correctly perform element-wise swap.
P2214 explains why const assignability is needed for the implementation of zip
. It stems from assignment operators not being ref qualified.