我發現一些線程暗示這不能完成,但沒有一個使用完全相同的運算符和條件組合,所以我想問一些更具體的問題。希望這意味着對某個人來說這是一個快速而簡單的答案......這種或那種方式!是否有可能使'=`更喜歡通過(刪除)複製分配進行轉換賦值?
考慮一個例子代理類,做存儲的較大塊中管理的值 - 在這個過於簡單,但代表性的例子:
class SomeProxyThing {
std::uint32_t storage;
public:
operator std::uint16_t() const
{
return storage & 0x0000FFFF;
}
SomeProxyThing &operator=(std::uint16_t const value)
{
storage &= 0xFFFF0000;
storage |= value;
}
};
我想所有分配通過定義用戶工作operator
s。用戶應該只能夠進入或退出'暴露'類型,在這種情況下std::uint16_t
。我可能會使用各種代理類類型,並希望它適用於所有這些類型。理想情況下,對於任何類型的組合,我只需鍵入someProxy = anotherProxy
,然後讓編譯器完成剩下的工作。
但是,當作業的左側和右側有相同或繼承相關的類型時,默認的複製賦值運算符 - 當然會與此目標衝突。它會複製整個storage
,從而破壞uint32_t
的另一半 - 而不是僅根據需要複製「暴露」值。正確的!對於大多數情況。但是,即使LHS和RHS類型相同,我也想要一種「按轉換分配」的方式。爲了避免這種情況,我可以:
- 重新定義拷貝賦值運算符執行「代理」複製使用用戶定義的
operator
秒 - 這是我一直在做什麼,但似乎有點哈克和一樣,打破可複製的struct
的狀態 - 我需要保留。它仍然memcpy()
s 無論如何在g++
,但我想定義的行爲。 - 或
= delete
複製賦值運算符(我們現在可以對TC類型進行操作)。但作業仍然嘗試使用它並拋出一個編譯錯誤 - 因爲delete
意味着'如果我是所選擇的超載而中止一個錯誤',而不是'將我排除在重載解析之外'。爲了解決這個問題,我必須明確地告訴編譯器使用轉換操作符,並從其結果分配:
SomeProxyThing a, b;
a = 42;
b = static_cast<std::uint16_t>(a);
// a.k.a.
b.operator=(a.operator std::uint16_t());
目前似乎沒有一種方法來告訴編譯器「忽略您首選的超載所產生的任何錯誤,並選擇下一個最好的錯誤'。在那兒?更一般地說,在這種情況下,有沒有什麼辦法/破解/可怕的kludge到強制編譯器自動使用/更喜歡某些operator
s?
換句話說,理想情況下,在
SomeProxyThing a, b;
a = 42;
b = a;
是b = a;
會真正做到這一點:
b = static_cast<std::uint16_t>(a);
// a.k.a.
b.operator=(a.operator std::uint16_t());
沒有我不必手動鍵入此,使用static_cast
,或實現命名的get/set方法。理想情況下,我希望對任何這樣的代理進行讀取/寫入,使其看起來像寫入代碼中的基本類型的讀取/寫入,全部使用=
。
我強烈懷疑這是不可能的......但確認就好了!
似乎是在您要求的矛盾:當副本將被做,你不想默認的拷貝賦值運算符的行爲,但你仍然希望類是平凡可複製。你不能同時擁有; trivially可複製意味着(其中包括)默認操作是正確的類。 – bogdan
@bogdan當然。我意識到,我想從一個相同類型的賦值通過轉換運算符來賦值,這是相當自相矛盾的,所以我懷疑這是可能的 - 只是想真正確認。在我目前的項目中,我使用了這個主題的幾個變體,這些變體都通過轉換運算符正確指定給每個其他變量 - 只有當LHS和RHS具有相同(或派生)類型時,纔會出現此問題。我真的只想懶惰,對所有組合使用相同的語法,但我的直覺是它不能完成。 –
'memcpy'ability是我真正的目標,而不是簡單的複製分配,但標準認爲它們與內在相關,原因很明顯。有[線程討論可能的改進,以_trivially copyable_和建議「的memcpy」 - 能夠類型的新類別(https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/wphImiqfX7Y)這可能會增加更多的細微差別,但我不知道實際上已經去過任何地方。 –