You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何GCC无法解析右值重载的用户定义转换运算符?

GCC无法解析右值重载的用户定义转换运算符问题

我编写了如下C++代码:

#include <iostream>
#include <string>

struct A {
    int x;
    int y;
};

struct B {
    A a;
    ~B(){
        std::cout << "deleted" << std::endl;
        a.x = 99;
        a.y = 99;
    }
    operator A & () &   {
        std::cout << "cast A&" << std::endl;
        return a;
    }
    operator A () && {
        std::cout << "cast A" << std::endl;
        return a;
    }
};

B make_b(){
    return {0,1};
}

int main() {
    const A & a = make_b();
    std::cout << a.x << std::endl;
    std::cout << a.y << std::endl;
}

这段代码在Clang编译器下输出符合预期:

cast A
deleted
0
1

但在GCC编译器下编译失败,报错信息如下:

Could not execute the program
Compiler returned: 1
Compiler stderr
<source>: In function 'int main()':
<source>:33:25: error: invalid user-defined conversion from 'B' to 'const A&' [-fpermissive]
   33 |     const A & a = make_b();
      |                   ~~~~~~^~
<source>:18:5: note: candidate is: 'B::operator A&() &' (near match)
   18 |     operator A & () &   {
      |     ^~~~~~~~
<source>:18:5: note:   passing 'B' as 'this' argument discards qualifiers
<source>:33:26: error: passing 'B' as 'this' argument discards qualifiers [-fpermissive]
   33 |     const A & a = make_b();
      |                          ^
<source>:18:5: note:   in call to 'B::operator A&() &'
   18 |     operator A & () &   {

问题分析

这是GCC与Clang在用户定义转换的重载决议逻辑上的差异导致的:

当执行const A& a = make_b();时,预期是调用右值限定的operator A() &&,生成临时A对象后,让const A&绑定到该临时对象(临时对象生命周期会被引用延长)。

但GCC的重载决议会优先尝试匹配返回A&的左值限定转换运算符operator A&() &——尽管该运算符要求this是左值,而make_b()返回的是右值B,调用它会违反左值限定,因此触发编译错误。

Clang则会正确排除不适用的左值限定运算符,转而选择右值限定的operator A() &&,因为其返回的临时A可以被const A&合法绑定。

解决方法

可以通过以下方式让代码在GCC上正常编译:

  • 修改右值转换运算符的返回类型为const A&,直接返回成员a的const引用:
operator const A& () && {
    std::cout << "cast const A&" << std::endl;
    return a;
}
  • 在main中显式执行右值到A的转换,明确指定调用右值重载:
const A & a = static_cast<A>(make_b());
  • 添加一个const限定的左值转换运算符,作为备选匹配项:
operator const A& () const & {
    std::cout << "cast const A&" << std::endl;
    return a;
}

内容的提问来源于stack exchange,提问作者bradgonesurfing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 15:58:21