Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does operator() copy movable temporaries in Clang?

In the following C++23 program

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

int main() {
    A{}.f(); // ok
    A{}();   // Clang error
}

struct A is movable, and its member functions f() and operator() have explicit object parameter (this A).

In Clang compiler surprisingly A{}.f() works fine, but A{}() fails with the error:

<source>:10:5: error: call to implicitly-deleted copy constructor of 'A'
<source>:3:5: note: copy constructor is implicitly deleted because 'A' has a user-declared move constructor

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

Is there some difference between functions f() and operator() from the language standpoint that explains their observable treatment by the compiler?

like image 717
Fedor Avatar asked Sep 03 '25 03:09

Fedor


1 Answers

This is a confirmed clang bug. The program is well-formed. The expression A{}() is equivalent to(interpreted as) A{}.operator()() which clang accepts. Since A{} is a prvalue(and hence an rvalue), the overloaded call operator A::operator()(this A) is a viable option here for the call A{}.operator()().

From over.call:

A function call operator function is a function named operator() that is a member function with an arbitrary number of parameters. It may have default arguments. For an expression of the form

postfix-expression ( expression-listopt )

where the postfix-expression is of class type, the operator function is selected by overload resolution ([over.call.object]). If a surrogate call function is selected, let e be the result of invoking the corresponding conversion operator function on the postfix-expression; the expression is interpreted as

e ( expression-listopt )

Otherwise, the expression is interpreted as

postfix-expression . operator () ( expression-listopt ) 

like image 167
Anoop Rana Avatar answered Sep 04 '25 18:09

Anoop Rana