非const复制构造函数和隐式转换返回值 [英] Non-const copy constructor and implicit conversions on return value

查看:128
本文介绍了非const复制构造函数和隐式转换返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下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; //不编译
}

这在MSVC ++ 2010上编译得很好在MSVC它甚至工作,如果我删除 B 一起)。它不在GCC 4.6.0上:

  conv.cpp:在函数'A f()':
conv.cpp:13:9:错误:没有匹配的函数调用'A :: A(A)'
conv.cpp:13:9:注意:候选人是:
conv.cpp :6:2:note:A :: A(B)
conv.cpp:6:2:注意:没有已知的转换从参数1从'A'到'B'
conv.cpp: 5:2:note:A :: A(A&)
conv.cpp:5:2:note:没有已知的从参数1转换为'A'到'A&'
conv.cpp :4:2:note:A :: A(int)
conv.cpp:4:2:注意:参数1从'A'到'int'的已知转换

令人困惑的是消息没有已知的转换从参数1从'A'到'B'。考虑到 A :: operator B()的定义很好,这是怎么回事呢?

解决方案

错误在被拒绝的候选人列表上是相当清楚的。问题是,涉及C ++语言中的用户定义转换的隐式转换序列限于单个用户定义的转换:


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


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


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




  • 以下集合:lvalue-to-rvalue转换,数组到指针的转换和函数到指针的转换。



  • p>零或一个资格转换。



问题是,通过应用单个用户定义的转换,从点a) int rvalue到点b) B



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


Consider the following C++ code:

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
}

This compiles fine on MSVC++ 2010 (in fact, on MSVC it even works if I remove B altogether). It doesn't on 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’

What's confusing me is the message no known conversion for argument 1 from ‘A’ to ‘B’. How can this be true considering that A::operator B() is very well defined?

解决方案

The error is quite clear on the list of candidates that were rejected. The problem is that implicit conversion sequences involving a user defined conversion in the C++ language are limited to a single user defined conversion:

§13.3.3.1.2 [over.ics.user]/1 A user-defined conversion sequence consists of an initial standard conversion sequence followed by a user-defined conversion (12.3) followed by a second standard conversion sequence.

The standard conversion sequences are defined in §4[conv]:

[...] A standard conversion sequence is a sequence of standard conversions in the following order

  • Zero or one conversion from the following set: lvalue-to-rvalue conversion, array-to-pointer conversion, and function-to-pointer conversion.

  • Zero or one conversion from the following set: integral promotions, floating point promotion, integral conversions, floating point conversions, floating-integral conversions, pointer conversions, pointer to member conversions, and boolean conversions.

  • Zero or one qualification conversion.

The problem is that your code cannot get from point a) int rvalue to point b) B by applying a single user defined conversion.

In particular, all conversion sequences that are available start with a user defined conversion (implicit constructor A(int)) that yield an A rvalue. From there, the rvalue cannot be bound to a non-const reference to call A::A( A& ), so that path is discarded. All the other paths require a second user defined conversion that is not allowed, and in fact the only other path that would get us to point b) requires two other user defined conversions for a total of 3.

这篇关于非const复制构造函数和隐式转换返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆