繁体   English   中英

非const复制构造函数和返回值的隐式转换

[英]Non-const copy constructor and implicit conversions on return value

考虑以下C ++代码:

struct B { };
struct A
{
        A(int);
        A(A&); // missing const is intentional
        A(B);
        operator B();
};

A f()
{
        // return A(1); // compiles fine
        return 1; // doesn't compile
}

这在MSVC ++ 2010上编译得很好(事实上,在MSVC上,如果我完全删除B ,它甚至可以工作)。 它不在GCC 4.6.0上:

conv.cpp: In function ‘A f()’:
conv.cpp:13:9: error: no matching function for call to ‘A::A(A)’
conv.cpp:13:9: note: candidates are:
conv.cpp:6:2: note: A::A(B)
conv.cpp:6:2: note:   no known conversion for argument 1 from ‘A’ to ‘B’
conv.cpp:5:2: note: A::A(A&)
conv.cpp:5:2: note:   no known conversion for argument 1 from ‘A’ to ‘A&’
conv.cpp:4:2: note: A::A(int)
conv.cpp:4:2: note:   no known conversion for argument 1 from ‘A’ to ‘int’

让我感到困惑的是no known conversion for argument 1 from 'A' to 'B'的消息。 考虑到A::operator B()定义得非常好,这怎么可能呢?

因为你不能做多个隐式转换。 你必须使用A::A(A::A(int)::operator B())来完成这项工作,这就是编译器自己弄清楚它的步骤太多了。

我不认为DeadMG指出的“太多步骤可以自行计算”是原因。 我有3-4次转换的构造,编译器总是把它们搞得很好。

我认为问题在于不允许编译器代表自己将const引用转换为非const引用(只有当您使用强制转换明确告诉它时才允许这样做)。
由于对传递给复制构造const的临时对象的引用是const ,但复制构造函数不是,因此它找不到合适的函数。

编辑:我没有找到任何“真正的”代码(见下面的评论),但构建了一个多zigzag转换示例,实际编译没有错误在gcc 4.5下。 请注意,使用-Wall -Wextra也可以很好地编译,这让我很惊讶。

struct B
{
    signed int v;
    B(unsigned short in) : v(in){}
};

struct C
{
    char v;
    C(int in) : v(in){}
};

struct A
{
    int v;
    A(B const& in) : v(in.v){}
    operator C() { return C(*this); }
};

enum X{ x = 1 };

int main()
{
    C c = A(x);
    return 0;
}

被拒绝的候选人名单上的错误非常清楚。 问题是涉及用户定义的C ++语言转换的隐式转换序列仅限于单个用户定义的转换:

§13.3.3.1.2[over.ics.user] / 1用户定义的转换序列包括初始标准转换序列,后跟用户定义的转换(12.3),后跟第二个标准转换序列。

标准转换序列在§4[conv]中定义:

[...]标准转换序列是按以下顺序的一系列标准转换

  • 来自以下集合的零或一次转换:左值到右值的转换,数组到指针的转换以及函数到指针的转换。

  • 来自以下集合的零或一次转换:整数促销,浮点促销,积分转换,浮点转换,浮点积分转换,指针转换,成员转换指针和布尔转换。

  • 零或一个资格转换。

问题是你的代码无法通过应用单个用户定义的转换从点a) int rvalue到b) B点。

特别是,所有可用的转换序列都以用户定义的转换(隐式构造函数A(int) )开始,该转换产生A rvalue。 从那里,rvalue不能绑定到非const引用来调用A::A( A& ) ,因此该路径被丢弃。 所有其他路径都需要第二个用户定义的转换是不允许的,事实上,唯一能让我们指向b)的其他路径需要另外两个用户定义的转换,总共3个。

该错误列出了所有可能使用的候选项,以及它们无法使用的原因。 它列出了B的转换,因为它是其中一个构造函数,但在这种情况下它不知道如何使用它,所以它没有。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM