2016-02-25 116 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