C++ – How to Perform Move Elision in Explicit Object Member Functions for C++23

c++c++23copy-elisionexplicit-object-parameterlanguage-lawyer

If one calls explicit object member function of a temporary, must the move of the temporary be elided in the explicit object parameter?

Consider the following example, where struct A has move constructor deleted and f(this A) is invoked for a temporary object A:

struct A {
    A() {}
    A(A&&) = delete;
    void f(this A) {}
};

int main() {
    A{}.f();
}

The program is accepted in GCC, but both Clang and MSVC reject it:

call to deleted constructor of 'A'

error C2280: 'A::A(A &&)': attempting to reference a deleted function

Online demo: https://gcc.godbolt.org/z/rbv14cnz5

Which compiler is correct here?

Best Answer

This is CWG2813. As the issue description notes, the wording in C++23 requires a glvalue for the left operand of the dot operator, which implies that if the left operand is a prvalue, it must be converted to a glvalue first (materialized), which prevents copy/move elision. This outcome is undesirable; we would like to have the prvalue initialize the explicit object parameter directly. So, a change was made to the wording and it was approved as a DR. It will take compilers a while to catch up, but the intent is that the example should be accepted.