Default Swap Functions

ISO/IEC JTC1 SC22 WG21 N2584 = 08-0094 - 2008-03-16

Lawrence Crowl, Lawrence@Crowl.org, crowl@google.com

Introduction

Exploiting move semantics and interacting with standard containers may require writing class-specific swap functions. As these functions have significant common implementations, the ability to specify default implementations for them would improve programmer productivity.

Proposal

We propose to extend the =default syntax of N2346 Defaulted and Deleted Functions to specify a default implementation.

Semantically, the default implementation of the swap member function is a recursive swap of its subobjects.

For example,


struct Derived
:
    public Base
{
    std::vector<int> vec;
    std::string name;

    void swap(Derived&& x)
    {
        using std::swap;
        swap(static_cast<Base&>(*this), static_cast<Base&>(x));
        swap(vec, x.vec);
        swap(name, x.name);
    }
};

In addition, a definition of a namespace-scope swap function may be necessary or desireable. The corresponding default implementation is:


void swap(Derived& x, Derived& y) { x.swap(y); }

Howard Hinnant voices the following concern:

I want to be careful that we don't break current code that we may not be expecting: such as member swap calls std::swap for *this. I don't think we've done that yet.

Note, however, that such code would be redundant with the current use of swap in the standard library.

Wording

The proposed wording shows changes from an editing draft preliminary to the March 2008 mailing. The base text does not form an officially accepted draft. Earlier drafts have slightly different text.

Note that the edits to section 8.4, 8.4.1, and 8.4.2 are identical in this paper and in N2583 Default Move Functions.

8.4 Function definitions [dcl.fct.def]

End the section after paragraph 8.

8.4.1 Explicitly-defaulted definitions [dcl.fct.def.default]

Add a new section comprising paragraph 9 of the old 8.4 Function definitions [dcl.fct.def].

Split the paragraph into three paragraphs, with the first paragraph containing the introductory sentence, the second paragraph containing the special member discussion, and the third paragraph containing the note and example.

Edit the resulting second paragraph as follows.

Only special Special member functions may be explicitly defaulted, and the implementation shall define them as if they had implicit definitions (12.1, 12.4, 12.8). A special member function that would be implicitly defined as deleted shall not be explicitly defaulted. A special member function is user-provided if it is user-declared and not explicitly defaulted on its first declaration. A user-provided explicitly-defaulted function is defined at the point where it is explicitly defaulted.

8.4.1.2 Swap function defaults [dcl.fct.def.swap]

Add a new section with the following paragraphs.

A swap non-member function (20.1.1 [utility.arg.requirements]) has no implicit default, but may be explicitly defaulted. The default definition shall invoke the swap member function on the first argument, passing it the second argument.

[Example: The definition


void swap(T& x, T& y) = default;

is equivalent to


void swap(T& x, T& y) { x.swap(y); }

end example]

A swap member function has no implicit default, but may be explicitly defaulted. The default definition shall swap its bases and variables from the corresponding bases and variables of the swap member function parameter.

[Example: Given the class definition


struct Derived : public Base {
    std::vector<int> vec;
    std::string name;
    void swap(Derived& x);
};

the member function definition


void Derived::swap(Derived& x) = default;

is equivalent to


void Derived::swap(Derived&& x) {
    using std::swap;
    swap(static_cast<Base&>(*this), static_cast<Base&>(x));
    swap(vec, x.vec);
    swap(name, x.name);
}

end example]

If the default implementation of a swap member function would swap a reference variable, the use of the swap member function default is ill-formed.

8.4.2 Deleted definitions [dcl.fct.def.delete]

Add a new section comprising paragraph 10 of the old 8.4 Function definitions [dcl.fct.def].