C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Possible Flaw/Hole in the type system

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Thu, 25 Sep 2025 01:32:21 -0400
On Thu, Sep 25, 2025 at 1:16 AM Jan Schultke via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> > I'm trying to determine if this is actually a defect in the language,
> > or am I missing something?:
>
> The problem is that any operator-> returns a pointer, not a reference,
> and so the information about whether you're applying "->" to an lvalue
> or rvalue is lost. [expr.ref] simply states:
>
> > The expression E1->E2 is converted to the equivalent form (*(E1)).E2
>
> I guess it's not entirely unfixable though. We could say that the
> result of dereferencing the pointer is converted to an xvalue if E1 is
> an rvalue. Perhaps this wouldn't even break too much code [...]


It would break lots, because we're not talking here about the built-in
operator-> that you quoted; we're talking about the overloaded operator->.

struct T {
  int fn() &;
};
struct Optional {
  T t_;
  const T* operator->() const { return &t_; }
  T* operator->() { return &t_; }
};
struct SharedPtr {
  T *p_;
  T *operator->() const { return p_; }
};
Optional getOptional();
SharedPtr getSharedPtr();
int main() {
  getOptional()->fn(); // getOptional() is a prvalue, and we'd like fn()
not to be callable here
  getSharedPtr()->fn(); // getSharedPtr() is a prvalue, but we *must*
continue to call fn() here; there's nothing wrong with this code
}

Now, we could at least give a (QoI) compiler warning if `expr->f()` on an
rvalue `expr` invokes a non-const `operator->` member function. (Test cases
here. <https://godbolt.org/z/9Mo1W1jaK>) That seems tricky to
implement, but maybe it's not so hard as I'm thinking.
In fact, my P1144 Clang fork already gives a warning
<https://godbolt.org/z/KhdP47TEf> if `expr = rhs` on an rvalue `expr`
invokes a non-const `operator=`, because that's almost always a bug.

<source>:13:14: warning: possibly unintended assignment to an rvalue of
type 'Obj' [-Wassign-to-class-rvalue]
   13 | getObj() = 42;
      | ~~~~~~~~ ^

–Arthur

Received on 2025-09-25 05:32:40