为何Clang中operator()会拷贝可移动临时对象?C++23代码解析
C++23显式对象参数:成员函数与调用运算符的行为差异
先看这段C++23代码:
struct A { A() {} A(A&&) = default; void f(this A) {} void operator() (this A) {} }; int main() { A{}.f(); // ok A{}(); // Clang error }
结构体A拥有默认移动构造函数,成员函数f()和调用运算符operator()都使用了C++23的显式对象参数(this A,按值传递)。在Clang编译器中,A{}.f()可以正常编译运行,但A{}()会触发如下错误:
:10:5: error: call to implicitly-deleted copy constructor of 'A' :3:5: note: copy constructor is implicitly deleted because 'A' has a user-declared move constructor
问题本质:这是Clang的实现缺陷,而非标准规定的差异
从C++23标准层面来说,带显式对象参数的普通成员函数和调用运算符的参数传递规则是完全一致的:
- 当调用者是右值(比如
A{}这种临时对象)时,按值传递的this参数应该通过移动构造来初始化,而非拷贝构造。 A{}.f()能正常运行,是因为Clang正确处理了普通成员函数的显式对象参数,用移动构造传递临时对象;而A{}()的处理中,Clang错误地尝试调用已被删除的拷贝构造函数,这不符合标准要求。
其他编译器(如GCC)对这段代码的处理是符合标准的,不会触发错误,进一步验证了这是Clang的实现问题。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

