An example of a well-formed class definition with a defaulted special member function that the compiler makes deleted

Viewed 98

In the C++20 standard, [dcl.fct.def.default], Explicitly-defaulted functions:

2 The type T1 of an explicitly defaulted special member function F is allowed to differ from the type T2 it would have had if it were implicitly declared, as follows:

(2.1) — T1 and T2 may have differing ref-qualifiers;

(2.2) — T1 and T2 may have differing exception specifications; and

(2.3) — if T2 has a parameter of type const C&, the corresponding parameter of T1 may be of type C&.

If T1 differs from T2 in any other way, then:

(2.4) — if F is an assignment operator, and the return type of T1 differs from the return type of T2 or T1’s parameter type is not a reference, the program is ill-formed;

(2.5) — otherwise, if F is explicitly defaulted on its first declaration, it is defined as deleted;

(2.6) — otherwise, the program is ill-formed

Could anybody provide an example of a special member function explicitly defaulted and that is deleted by the compiler. The function declaration should be well-formed.

1 Answers

The example from P0641, whence this wording:

struct MyType {
  MyType(MyType&);  // no 'const'
};

template <typename T>
struct Wrapper {
  Wrapper(const Wrapper&) = default;
  T t;
};

Wrapper<MyType> var;  // fails to instantiate

Pretend there was actually a default constructor.

This was previously ill-formed. Now, T1 (Wrapper's copy constructor) differs from it what it would have been were it implicitly declared (would have been Wrapper(Wrapper&) per [class.copy.ctor]/7). This doesn't match the cases in the first set of bullets (here T1 has const& but not T2, the bullet is in the opposite order), so we fall through to the second set of bullets - and we end up with Wrapper<MyType>'s copy constructor being deleted.


A good example of where this would've come up in code is something like std::tuple (see LWG2086), where prior to these changes:

struct A {
  A();
  A(A&);
};
std::tuple<A> x; // ill-formed

Now, this is well-formed, just that tuple<A> isn't copyable.

Related