The question is basically the same as the old Why aren't there compiler-generated swap() methods in C++0x?, but provides more recent context and asks for a more up-to-date answer.
If for some class C
swap(C&, C&)
is implemented much more efficiently than std::swap<C>
, then each class D
that contains C
as a data member or inherits C
must define its own swap(D&, D&)
in order to benefit from swap(C&, C&)
's efficiency (std::swap<D>
only calls D
's move constructor and move assignment operator, which in turn call C
's move operations). Then each class that contains a D
data member or inherits D
has to implement its own swap()
for maximum efficiency, and so on.
The top answer to Move semantics == custom swap function obsolete? states that a custom swap()
can often be much faster. But writing even a trivial custom definition is error-prone: each base class and each data member has to be swapped; each newly-added base class or data member requires a modification of the custom swap()
's definition.
n3746 proposes adding a new operator to replace the free swap()
function. The proposal has been rejected because the committee felt that already implemented swap()
overloads would be retained and called by new code for backwards compatibility. The coexistence of the swap operator and the free swap()
function is considered undesirable. But is there a reason why the free friend
swap()
function cannot be implicitly generated or declared by the user as defaulted? For example:
class D : public Base
{
public:
friend void swap(D&, D&) = default;
private:
C c_;
std::vector<int> v_;
double r_;
};
The compiler could generate the following definition:
void swap(D& a, D& b) noexcept(...)
{
using std::swap;
swap(static_cast<Base&>(a), static_cast<Base&>(b));
swap(a.c_, b.c_);
swap(a.v_, b.v_);
swap(a.r_, b.r_);
}
Here noexcept(...)
stands for noexcept(true)
if swapping each subobject is noexcept(true)
; noexcept(false)
otherwise.
The compiler could implicitly declare and generate swap()
for a class that has no user-declared copy/move constructor/assignment operators. This is somewhat risky due to the absence of std::swap()
's strong exception guarantee. But the implicitly-generated copy and move special members lack strong exception guarantee too, so this shouldn't be much of a problem.
The compiler-generated swap()
would get rid of error-prone custom boilerplate definitions and speed up swapping objects of classes and structs, for which no custom swap()
is implemented. Is there a technical or a philosophical reason why this feature hasn't been proposed for the C++ standard? Is the feature relatively unimportant? Or is this an oversight/omission?