Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

CWG2813 [expr.ref] Class member access currently requires glvalue, but it shouldn't #411

Copy link
Copy link
Closed
cplusplus/draft
#6906
cplusplus/draft#6906
@brevzin

Description

@brevzin
Issue body actions

Reference (section label): [expr.ref]

Issue description: [expr.ref]/2 currently starts:

For the first option (dot) the first expression shall be a glvalue.

This means that in X().f(), because X() is a prvalue, the temporary materialization conversion is applied ([basic.lval]/7). Up until C++23, this detail wasn't significant since for any non-static member function f(), f()'s object parameter would have had reference type, so there was no other real alternative.

But since C++23, with deducing this, we can now have non-static member functions that take their explicit object parameter by value. Which means that this example (from Johel Ernesto Guerrero Peña) is ill-formed:

struct X {
  X() = default;

  X(const X&) = delete;
  X(X&&) = delete;
  X& operator=(const X&) = delete;
  X& operator=(X&&) = delete;

  void f(this X self) { }
};

void f() {
  X{}.f();
}

X{}.f() currently forces a temporary materialization conversion, which means that the explicit object parameter self is initialized not from the prvalue X{} (which would work) but rather from an xvalue, which does not.

But taking a function pointer to &X::f and invoking it with X{} would of course be fine. The more convenient direct member syntax should also be fine, and indeed P0847 contained motivating examples of using by-value member functions that take advantage of guaranteed copied elision.

Suggested resolution:

Is the quoted sentence actually useful? For the existing non-static member function use-cases, because the object parameter already has reference type, the temporary materialization conversion will already be applied. It seems to simply force an undesired move construction in this case. The resolution might simply be:

For the first option (dot) the first expression shall be a glvalue. For the second option (arrow) the first expression shall be a prvalue having pointer type. The expression E1->E2 is converted to the equivalent form (*(E1)).E2; the remainder of [expr.ref] will address only the first option (dot).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.