[英]Assignment operator to reference template type requires non-const overload
我正在努力解決復制分配操作員問題。 盡管我有一些想法(最后列出),但我無所適從。 這是一個問題,因為我使用的是第3方庫,其類無法控制。
假設您有一個帶有復制分配運算符的模板化容器。 此運算符接受具有不同模板的另一個容器,並嘗試static_cast其他類型。
template <class U>
vec2<T>& operator=(const vec2<U>& v) {
x = static_cast<T>(v.x);
y = static_cast<T>(v.y);
return *this;
}
這對於簡單的分配是很好的,但是,當對T使用引用時,會出現有關const值類型的編譯錯誤。 如果添加另一個接受非const引用的重載,它將進行編譯並工作。
我做了一個簡單的例子,應該可以說明這個問題。
template <class T>
struct vec2 final {
vec2(T x_, T y_)
: x(x_)
, y(y_) {
}
template <class U>
vec2(const vec2<U>& v)
: x(static_cast<T>(v.x))
, y(static_cast<T>(v.y)) {
}
template <class U>
vec2<T>& operator=(const vec2<U>& v) {
if (this == &v)
return *this;
x = static_cast<T>(v.x);
y = static_cast<T>(v.y);
return *this;
}
// Fix :
/*
template <class U>
vec2<T>& operator=(vec2<U>& v) {
x = static_cast<T>(v.x);
y = static_cast<T>(v.y);
return *this;
}
*/
T x;
T y;
};
以及我如何嘗試使用它:
int main(int, char**) {
vec2<int> v0 = { 0, 0 };
vec2<int> v1 = { 1, 1 };
vec2<int&> test[] = { { v0.x, v0.y }, { v1.x, v1.y } };
vec2<int> muh_vec2 = { 2, 2 };
test[0] = muh_vec2;
printf("{ %d, %d }\n", test[0].x, test[0].y);
return 0;
}
最新的AppleClang將產生以下錯誤:
main4.cpp:18:7: error: binding value of type 'const int' to reference to type 'int'
drops 'const' qualifier
x = static_cast<T>(v.x);
^ ~~~
main4.cpp:63:10: note: in instantiation of function template specialization 'vec2<int
&>::operator=<int>' requested here
test[0] = muh_vec2;
^
我從中了解到的是,編譯器以某種方式嘗試通過const值進行賦值。 但是,為什么並且有一個非侵入式的解決方案呢?
我在這里確實找到了類似的問題: 模板賦值運算符重載了奧秘
閱讀此問題后,我的結論是:可能是默認賦值運算符引起了該問題? 我仍然不明白為什么,但是:/
這是一個在線示例: https : //wandbox.org/permlink/Fc5CERb9voCTXHiN
template <class U>
vec2<T>& operator=(const vec2<U>& v)
在此方法中, v
是右側const視圖的名稱。 如果U
為int
,則vx
為const int
。
如果T
是int&
,則this->x
是int&
。
this->x = static_cast<int&>(v.x);
這顯然是非法的:您不能將const int靜態轉換為非const引用。
一般的解決方案基本上需要重建std::tuple
或std::pair
機械。 SFINAE可用於引導它。 但是總的來說,包含引用的結構和包含值的結構通常是完全不同的野獸。 為兩者使用一個模板是有問題的。
template <class T>
struct vec2 final {
template<class Self,
std::enable_if_t<std::is_same<std::decay_t<Self>, vec2>>{}, bool> =true
>
friend auto as_tuple( Self&& self ){
return std::forward_as_tuple( std::forward<Self>(self).x, std::forward<Self>(self).y );
}
那么我們可以進行SFINAE測試以確定as_tuple(LHS)=as_tuple(RHS)
是否有效。
進行構造是另一個痛苦,因為LHS的元組類型需要先進行按摩,然后才能進行可構造性測試。
您編寫的代碼越通用,所需的工作就越多。 在編寫無限通用代碼之前,請考慮實際用例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.