Title
Lookup for determining rewrite targets
Status
open
Section
12.2.2.3 [over.match.oper]
Submitter
Richard Smith

Created on 2023-10-13.00:00:00 last changed 4 months ago

Messages

Date: 2023-11-15.00:00:00

Additional notes (November, 2023)

P2468R2 also made the following example (derived from real-world code) ambiguous between the reversed built-in candicate and the user-provided operator==:

  template<class T>
  struct Ptr
  {
    bool operator==(T* p) const noexcept { return m_p == p; }
    operator T*() const noexcept { return m_p; }

    T* m_p;
  };

  void foo(Ptr<int> a, Ptr<int> b)
  {
    assert(a == b);
  }

EWG 2024-03-18

EWG invites a paper to propose a change.

Date: 2023-11-08.17:45:43

CWG 2023-10-20

CWG seeks the advice of EWG whether fine-tuning of the "rewrite target" rules is desired, and what exactly those rules should be. See paper issue #1688.

EWG 2023-11-07

The intent is to check for the existence of a declaration that differs only in the operator name (ie, bx should work, by should be ill-formed).

This outcome also resolves issue 2797, but, more importantly, partially reverts P2468R2 (The Equality Operator You Are Looking For), applied in July 2022. In particular, the following example added thereby is no longer well-formed:

  struct B {
    bool operator==(const B&); // #2
  };
  struct C : B {
    C();
    C(B);
    bool operator!=(const B&); // #3
  };
  bool c1 = B() == C(); // OK, calls #2; reversed #2 is not a candidate because search for operator!= in C finds #3

Back to EWG for confirmation.

Date: 2023-10-13.00:00:00

Consider:

  struct X {
    operator int();
    friend bool operator==(X, int);
    friend bool operator!=(X, int);  // #1
  } x;

  bool bx = x == x;    // error: lookup for rewrite target determination does not find hidden friend #1

  struct Y {
    operator int();
    friend bool operator==(Y, int);   // #2
  } y;

  bool operator!=(Y, int);            // #3

  bool by = y == y;                   // OK, #2 is not a rewrite target because lookup finds #3

A similar issue arises for function-scope declarations:

  struct X { operator int(); };

  bool f(X x) {
    bool operator==(X, int);
    return x == x;              // error
  }

  bool g(X x) {
    bool operator==(X, int);
    bool operator!=(X, int);
    return x == x;              // error
  }

  bool operator!=(X, int);

  bool h(X x) {
    bool operator==(X, int);
    return x == x;              // OK
  }

  bool i(X x) {
    bool operator==(X, int);
    bool operator!=(X, int);
    return x == x;              // OK
  }

Are these outcomes as intended? For the bx case at least, probably not.

History
Date User Action Args
2024-01-01 08:12:36adminsetmessages: + msg7562
2023-10-20 21:07:14adminsetmessages: + msg7472
2023-10-13 00:00:00admincreate