This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
[Voted into the WP at the March, 2011 meeting.]
N3092 comment FI 1It 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.
Proposed resolution (November, 2010):
Change 9.5.2 [dcl.fct.def.default] paragraphs 1-5 as follows:
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
ita 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 private: 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], 11.4.5.3 [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], 11.4.5.3 [class.copy.ctor]). This rule enablesDeclaring 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][Example:
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::nontrivial1() = default; // notinlinefirst declarationstruct nontrivial2 { nontrivial2(); }; inline nontrivial2::nontrivial2() = default; // not first declaration struct nontrivial3 { virtual ~nontrivial3() = 0; // virtual }; inline nontrivial3::~nontrivial3() = default; // not first declaration—end example]
Change 11.4.5 [class.ctor] paragraph 5 as follows:
Change 11.4.7 [class.dtor] paragraph 3 as follows:
...A destructor is trivial if it isneithernot user-providednor deletedand...
Change 11.4.5.3 [class.copy.ctor] paragraph 13 as follows:
A copy/move constructor for class X is trivial if it isneithernot user-providednor deletedand...
Change 11.4.5.3 [class.copy.ctor] paragraph 27 as follows:
A copy/move assignment operator for class X istrivialtrivial if it isneithernot user-providednor deletedand...
This resolution also resolves issues 1136, 1137, 1140, 1145, 1149, and 1208.