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


2586. Explicit object parameter for assignment and comparison

Section: 11.10.1  [class.compare.default]     Status: CD6     Submitter: Barry Revzin     Date: 2022-05-07     Liaison: EWG

[Accepted at the July, 2022 meeting.]

"Deducing this" allows to declare assignment and comparison operator functions as explicit object member functions.

However, such an assignment operator can never be a copy or move assignment operator, which means it always conflicts with the implicitly-defined one:

  struct C {
    C& operator=(this C&, C const&); // error: can't overload with the copy assignment operator
  };

Similarly, operator== or operator<=> can be declared with an explicit object parameter, but they cannot be defaulted:

  struct D {
    bool operator==(this D const&, D const&) = default; // error: not a kind of comparison that can be defaulted
  };

There seems to be no reason to disallow that, for people who prefer writing all of their members with explicit object parameters.

Suggested resolution:

  1. Change in 11.4.6 [class.copy.assign] paragraph 1 as follows:

    A user-declared copy assignment operator X::operator= is a non-static non-template member function of class X with exactly one non-object parameter of type X, X&, const X&, volatile X&, or const volatile X&.
  2. Change in 11.4.6 [class.copy.assign] paragraph 3 as follows:

    A user-declared move assignment operator X::operator= is a non-static non-template member function of class X with exactly one non-object parameter of type X&&, const X&&, volatile X&&, or const volatile X&&.
  3. Change in 11.10.1 [class.compare.default] paragraph 1 as follows:

    A defaulted comparison operator function (12.4.3 [over.binary]) for some class C shall be a non-template function that is
    • a non-static const non-volatile member of C having one parameter of type const C& and either no ref-qualifier or the ref-qualifier &, or or friend of C and
    • a friend of C having either has two parameters of type const C& or two parameters of type C , where the implicit object parameter (if any) is considered to be the first parameter..

Additional notes (May, 2022):

Forwarded to EWG with paper issue 1235, by decision of the CWG chair.

Approved by EWG telecon 2022-06-09 and EWG 2022-06 electronic poll.

See vote.

Additional notes (July, 2022):

The suggested resolution makes the following a copy assignment operator, suppressing the implicitly-declared one, which is surprising:

  struct B {
    B &operator =(this int, const B &); // copy assignment operator
  };

Proposed resolution (approved by CWG 2022-07-15):

  1. Change in 9.5.2 [dcl.fct.def.default] paragraph 2 as follows:

    The type T1 of an An explicitly defaulted special member function F F1 with type T1 is allowed to differ from the corresponding special member function F2 with type T2 it would have had if it were that would have been implicitly declared, as follows:
    • T1 and T2 may have differing ref-qualifiers;
    • if F2 has an implicit object parameter of type "reference to C", F1 may be an explicit object member function whose explicit object parameter is of type "reference to C";
    • T1 and T2 may have differing exception specifications; and
    • if T2 F2 has a non-object parameter of type const C&, the corresponding non-object parameter of T1 F1 may be of type C&.
    If T1 differs from T2 in any other a way other than as allowed by the preceding rules, then:
    • if F F1 is an assignment operator, and the return type of T1 differs from the return type of T2 or T1 F1's non-object parameter type is not a reference, the program is ill-formed;
    • otherwise, if F F1 is explicitly defaulted on its first declaration, it is defined as deleted;
    • otherwise, the program is ill-formed.
  2. Change in 11.4.6 [class.copy.assign] paragraph 1 as follows:

    A user-declared copy assignment operator X::operator= is a non-static non-template member function of class X with exactly one non-object parameter of type X, X&, const X&, volatile X&, or const volatile X&.
  3. Change in 11.4.6 [class.copy.assign] paragraph 3 as follows:

    A user-declared move assignment operator X::operator= is a non-static non-template member function of class X with exactly one non-object parameter of type X&&, const X&&, volatile X&&, or const volatile X&&.
  4. Change in 11.10.1 [class.compare.default] paragraph 1 as follows:

    A defaulted comparison operator function (12.4.3 [over.binary]) for some class C shall be a non-template function that is
    • a non-static const non-volatile member of C having one parameter of type const C& and either no ref-qualifier or the ref-qualifier &, or or friend of C and
    • a friend of C having either has two parameters of type const C& or two parameters of type C , where the implicit object parameter (if any) is considered to be the first parameter..