以下示例是否应该编译?
struct B;
struct A
{
A(B*&&){}
};
struct B : A
{
B() : A(this){}
};
int main(){}
在LWS上使用clang进行编译,但是使用gcc我得到:
参数1从'B * const'到'B *&&'
没有已知的转换
如果我添加const
,它就会编译。
我还想指出MSVC也错了:
无法将参数2从'B * const'转换为'B *&&'
所以看起来我们在两个编译器中有一个错误。
BUGS FILED
答案 0 :(得分:8)
是的,那应该编译。
将this
实现为cv T* const
是不正确的(其中cv是函数的cv限定符,如果有的话,T
是类类型)。 this
不是const
,而只是内置类型的prvalue表达式(不可修改)。
很多人认为,因为你不能修改this
它必须是const
,但正如Johannes Schaub - litb很久以前评论的那样,更好的解释是这样的:
// by the compiler
#define this (__this + 0)
// where __this is the "real" value of this
很明显,您无法修改this
(例如,this = nullptr
),但也请注意,此类说明无需const
。 (而你在构造函数中的值只是临时值。)
答案 1 :(得分:6)
我说clang是对的 - 代码应该编译。出于某种原因,GCC认为this
指针为const
,尽管如下:
类
this
的成员函数中X
的类型为X*
。如果成员函数声明为const
,则其类型为const X*
,如果成员函数声明为volatile
,则其类型为volatile X*
,如果成员函数声明为const volatile
,其类型为const volatile X*
。
因此,在这种情况下,this
应为prvalue B*
,并且与B*&&
完全绑定。但是,请注意,在将this
绑定到右值引用时,this
的值将被复制到临时对象中,而引用将被绑定到该对象。这可确保您永远不会实际修改原始this
值。
对类型“cv1
T1
”的引用由类型为“cv2T2
”的表达式初始化,如下所示:
[...]
[...]或引用应为右值参考。
如果是初始化表达式
是xvalue,类prvalue,数组prvalue或函数左值和[...],或
有一个类类型(即T2是类类型),[...]
然后[...]
否则,使用非参考拷贝初始化(8.5)的规则,从初始化表达式创建并初始化类型为“cv1 T1”的临时类型。然后将引用绑定到临时。 [...]