以下代码触发此错误:
1>main.cpp(38): error C2280: 'CSet<uint32>::CSetHelper &CSet<uint32>::CSetHelper::operator =(const CSet<uint32>::CSetHelper &)': attempting to reference a deleted function
1>main.cpp(27): note: compiler has generated 'CSet<uint32>::CSetHelper::operator =' here
代码
typedef unsigned int uint32;
template<class I> class CSet
{
protected:
uint32 u4Bits;
public:
class CSetHelper
{
protected:
uint32& ru4Var;
uint32 u4Mask;
public:
CSetHelper(uint32& ru4_var, uint32 u4_mask)
: ru4Var(ru4_var), u4Mask(u4_mask) {}
operator uint32 () const
{
return ru4Var & u4Mask;
}
void operator =(uint32 i)
{
if (i)
const_cast<uint32&>(ru4Var) |= u4Mask;
else
const_cast<uint32&>(ru4Var) &= ~u4Mask;
}
};
CSet() : u4Bits(0) {}
CSetHelper operator [](I i)
{
return CSetHelper(u4Bits, 1 << i);
}
};
int main(int argc, char** argv)
{
CSet<uint32> sFlags;
sFlags[0] = sFlags[1];
return 0;
}
这是在VS2015中,我知道他们对编译器所做的更改(detailed here)。但我不明白为什么它会触发。
理论上它应该使用正确的转换和赋值运算符,但它似乎并不是。
更新
使用Ideone.com和GCC 5.1:
prog.cpp: In member function 'CSet<unsigned int>::CSetHelper& CSet<unsigned int>::CSetHelper::operator=(const CSet<unsigned int>::CSetHelper&)':
prog.cpp:8:8: error: non-static reference member 'uint32& CSet<unsigned int>::CSetHelper::ru4Var', can't use default assignment operator
class CSetHelper
^
prog.cpp: In function 'int main(int, char**)':
prog.cpp:45:12: note: synthesized method 'CSet<unsigned int>::CSetHelper& CSet<unsigned int>::CSetHelper::operator=(const CSet<unsigned int>::CSetHelper&)' first required here
sFlags[0] = sFlags[1];
所以似乎问题是参考成员。我可以通过将其作为指针来修复它,但我想知道它为什么不能默认复制它。
答案 0 :(得分:1)
课程CSetHelper
包含参考uint32& ru4Var;
。
编译器为这些类型创建赋值运算符和复制构造函数为已删除(= delete
),因为无法重新定位引用。
答案 1 :(得分:1)
编译器是正确的。此代码格式错误。我们来看看这一行:
sFlags[0] = sFlags[1];
编译器可以采用两种方法来完成该操作:
CSetHelper& operator=(const CSetHelper&) = delete; // (1)
void operator=(uint32 ); // (2), via operator uint32()
虽然第二个是可能的并且可能是你想要的,但第一个是重载分辨率的更好的候选者,因为它是完全匹配而后者涉及用户定义的转换。复制赋值运算符仍处于重载范围内 - 由于具有引用成员,它只是被隐式删除。删除的函数仍然参与重载解析,如果选中,它们只会使程序格式错误。