Explicitly-defaulted non-public special member functions
9.5.2 [dcl.fct.def.default]

Created on 2010-08-02.00:00:00 last changed 102 months ago


Date: 2011-03-15.00:00:00

[Voted into the WP at the March, 2011 meeting.]

Date: 2010-11-15.00:00:00

Proposed resolution (November, 2010):

  1. Change 9.5.2 [dcl.fct.def.default] paragraphs 1-5 as follows:

  2. A function definition of the form:

      attribute-specifieropt decl-specifier-seqopt declarator = default ;

    is called an explicitly-defaulted definition. A function that is explicitly defaulted shall

    • be a special member function,

    • have the same declared function type (except for possibly differing ref-qualifiers and except that in the case of a copy constructor or copy assignment operator, the parameter type may be “reference to non-const T”, where T is the name of the member function's class) as if it had been implicitly declared, and

    • not have default arguments, and.

    • not have an exception-specification.

    [Note: This implies that parameter types, return type, and cv-qualifiers must match the hypothetical implicit declaration. —end note]

    An explicitly-defaulted function may be declared constexpr only if it would have been implicitly declared as constexpr, and may have an explicit exception-specification only if it is compatible (14.5 [except.spec]) with the exception-specification on the implicit declaration. If it a function is explicitly defaulted on its first declaration,

    • it shall be public,

    • it shall not be explicit,

    • it shall not be virtual,

    • it is implicitly considered to be constexpr if the implicit declaration would be,

    • it is implicitly considered to have the same exception-specification as if it had been implicitly declared (14.5 [except.spec]), and

    • in the case of a copy constructor, move constructor, copy assignment operator, or move assignment operator, it shall have the same parameter type as if it had been implicitly declared.

    [Note: Such a special member function may be trivial, and thus its accessibility and explicitness should match the hypothetical implicit definition; see below. —end note] [Example:

      struct S {
        constexpr S() = default;                 //ill-formed: implicit S() is not constexpr
        S(int a = 0) = default;                  // ill-formed: default argument
        void operator=(const S&) = default;      // ill-formed: non-matching return type
        ~S() throw(int) = default;               // ill-formed: exception specification doesn't match
        int i;
        S(S&);                                   // OK: private copy constructor
      S::S(S&) = default;                        // OK: defines copy constructor

    end example]

    Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the implementation shall provide implicit definitions for them (11.4.5 [class.ctor] 11.4.7 [class.dtor], [class.copy.ctor]), which might mean defining them as deleted. A special member function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. [Note: while an implicitly-declared special member function is inline (11.4.4 [special]), an explicitly-defaulted definition may be non-inline. Non-inline definitions are user-provided, and hence non-trivial (11.4.5 [class.ctor], 11.4.7 [class.dtor], [class.copy.ctor]). This rule enables Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base. —end note]


      struct trivial {
        trivial() = default;
        trivial(const trivial&) = default;
        trivial(trivial&&) = default;
        trivial& operator=(const trivial&) = default;
        trivial& operator=(trivial&&) = default;
        ~trivial() = default;
      struct nontrivial1 {
      nontrivial1::nontrivial1() = default;           // not inline first declaration
      struct nontrivial2 {
      inline nontrivial2::nontrivial2() = default;    // not first declaration
      struct nontrivial3 {
        virtual ~nontrivial3() = 0;                   // virtual
      inline nontrivial3::~nontrivial3() = default;   // not first declaration

    end example]

  3. Change 11.4.5 [class.ctor] paragraph 5 as follows:

  4. ...A default constructor is trivial if it is neither not user-provided nor deleted and...
  5. Change 11.4.7 [class.dtor] paragraph 3 as follows:

  6. ...A destructor is trivial if it is neither not user-provided nor deleted and...
  7. Change [class.copy.ctor] paragraph 13 as follows:

  8. A copy/move constructor for class X is trivial if it is neither not user-provided nor deleted and...
  9. Change [class.copy.ctor] paragraph 27 as follows:

  10. A copy/move assignment operator for class X is trivial trivial if it is neither not user-provided nor deleted and...

This resolution also resolves issues 1136, 1137, 1140, 1145, 1149, and 1208.

Date: 2010-08-02.00:00:00
N3092 comment FI 1

It should be allowed to explicitly default a non-public special member function on its first declaration. It is very likely that users will want to default protected/private constructors and copy constructors without having to write such defaulting outside the class.

Date User Action Args
2014-03-03 00:00:00adminsetstatus: fdis -> c++11
2011-04-10 00:00:00adminsetmessages: + msg3343
2011-04-10 00:00:00adminsetstatus: ready -> fdis
2010-11-29 00:00:00adminsetmessages: + msg3053
2010-11-29 00:00:00adminsetstatus: drafting -> ready
2010-08-02 00:00:00admincreate