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


2568. Access checking during synthesis of defaulted comparison operator

Section: 11.10.1  [class.compare.default]     Status: DRWP     Submitter: Nicolai Josuttis     Date: 2022-04-11

[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?

CWG 2023-06-17

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

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.