【发布时间】:2018-09-03 09:05:08
【问题描述】:
我正试图解决一个复制赋值运算符问题。我不知道到底发生了什么,尽管我有一些想法(在最后列出)。这是一个问题,因为我使用的是无法控制其类的 3rd 方库。
假设您有一个带有复制赋值运算符的模板化容器。此运算符接受具有不同模板的另一个容器,并尝试 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 值类型的编译错误。如果您添加另一个接受非常量引用的重载,它将编译并工作。
我做了一个简单的例子,应该有助于说明问题。
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 值进行分配。但是为什么以及是否有非侵入式的解决方案来解决这个问题?
我确实在这里找到了类似的问题:Template assignment operator overloading mystery
阅读问题后我的结论是:可能是默认赋值运算符导致了问题?我仍然不明白为什么:/
【问题讨论】:
-
x = static_cast<std::remove_reference_t<T>>(v.x)也许。或者甚至可能只是简单地x = v.x;并依赖于隐式转换。 -
所以 remove_reference 有效。你知道为什么吗?您知道不需要修改容器的替代方法吗?
-
我不确定我是否理解这个问题。您是在问如何在不修改所述代码的情况下修复错误代码?
-
“这是个问题,因为我使用的是第三方库,无法控制其类。”
-
我怀疑
vec2<T>根本就不是为T的引用类型而设计的。因此,在不修改vec的情况下解决问题的一种方法就是避免以这种方式使用它。
标签: c++ templates reference assignment-operator