2016-02-25 58 views
1

下面的代码触发此错误:C2280试图引用删除的功能

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) 。但我不明白为什么它会触发。

理论上它应该使用正确的转换和赋值操作符,但它似乎不是。

UPDATE

使用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]; 

如此看来问题是基准元件。我可以通过使它成为一个指针来解决它,但我想知道为什么它不能默认复制它。

+1

我的第一个猜测,一个编译器错误,所有不必要的代码都被剥离下来,程序编译得很好。 – Raxvan

+1

@Raxvan为了编译这个代码,你剥离了多少“不必要的”代码? – Barry

+0

如果你不使用这个类,它将不会被实例化,所以是的,我不知道你删除了什么...... – speps

回答

1

CSetHelper类包含参考uint32& ru4Var;

对于这种类型,编译器创建赋值运算符和复制构造函数为已删除(= delete),因为该引用不能被重新设置。

+0

“不创建”不是很正确 - 它创建它们为删除。 – Barry

+0

是的,我添加了一些使用GCC编译的信息,在这种情况下更有帮助。你是对的:) – speps

1

编译器是正确的。此代码格式不正确。让我们来看看这条线:

sFlags[0] = sFlags[1]; 

有两种方法,编译器可能需要履行这一操作:

CSetHelper& operator=(const CSetHelper&) = delete; // (1) 
void operator=(uint32);       // (2), via operator uint32() 

而第二是可能的,可能是由你意,首先是重载分辨率更好,因为它是完全匹配,后者涉及用户定义的转换。复制赋值运算符仍处于过载范围内 - 由于具有引用成员,它只是被隐式删除。已删除的函数仍然参与重载解析,如果选中它们只会使程序不合格。

+0

你是对的,我没有注意到'uint32&ru4Var;'。 – Raxvan

相关问题