Title
Access checking during synthesis of defaulted comparison operator
Status
dr
Section
11.10.1 [class.compare.default]
Submitter
Nicolai Josuttis

Created on 2022-04-11.00:00:00 last changed 2 weeks ago

Messages

Date: 2023-12-02.13:35:39

Proposed resolution (approved by CWG 2023-12-01):

Change in 11.10.1 [class.compare.default] paragraph 1 as follows:

... Name lookups and access checks in the implicit definition (9.5.2 [dcl.fct.def.default]) of a comparison operator function are performed from a context equivalent to its function-body . A definition of a comparison operator as defaulted that appears in a class shall be the first declaration of that function.
Date: 2023-12-02.13:35:39

CWG 2023-06-17

There is no implementation divergence; the first example is intended to be well-formed.

Date: 2024-03-15.00:00:00

[Accepted as a DR at the March, 2024 meeting.]

Consider:

  struct Base {
  protected:
    bool operator==(const Base& other) const = default;
  };

  struct Child : Base {
    int i;
    bool operator==(const Child& other) const = default;
  };

Per 11.10.1 [class.compare.default] paragraph 6,

Let xi be an lvalue denoting the i-th element in the expanded list of subobjects for an object x (of length n), where xi is formed by a sequence of derived-to-base conversions (12.2.4.2 [over.best.ics]), class member access expressions (7.6.1.5 [expr.ref]), and array subscript expressions (7.6.1.2 [expr.sub]) applied to x.

The derived-to-base conversion for this loses the context of access to the protected Base::operator==, violating 11.8.5 [class.protected] paragraph 1. The example is rejected by implementations, but ought to work.

For this related example, there is implementation divergence:

  struct B {
  protected:
    constexpr operator int() const { return 0; }
  };
  struct D : B {
    constexpr bool operator==(const D&) const = default;
  };
  template<typename T> constexpr auto comparable(T t) -> decltype(t == t) { return t == t; }
  constexpr bool comparable(...) { return false; }
  static_assert(comparable(D{}));

Is D::operator== deleted, because its defaulted definition violates the protected access rules? Is D::operator== not deleted, but synthesis fails on use because of the proctected access rules? Is the synthesis not in the immediate context, making the expression comparable(D{}) ill-formed?

History
Date User Action Args
2024-04-05 21:43:46adminsetstatus: ready -> dr
2024-03-20 14:10:31adminsetstatus: tentatively ready -> ready
2023-12-02 13:35:39adminsetmessages: + msg7530
2023-12-02 13:35:39adminsetstatus: review -> tentatively ready
2023-06-20 19:34:52adminsetmessages: + msg7331
2023-06-20 19:34:52adminsetstatus: open -> review
2022-04-11 00:00:00admincreate