我有以下非类型模板:
template<size_t MAX_SIZE>
struct Path{
struct Point{
float x;
float y;
}
};
Point segment[MAX_SIZE];
};
如果我现在声明两个不同的路径,则我无法将不同段的元素彼此分配,因为这些结构可能具有相同的结构,但类型不同:
Path<10> path_a ;
Path<30> path_b ;
path_a.segment[0].x = 1;
path_a.segment[0].y = 2;
path_b.segment[0] = path_a.segment[0]; // <- error C2679 in Visual Studio)
当然,如果我将“点”和“路径”的定义分开,则分配将起作用:
struct Point{
float x;
float y;
};
template<size_t MAX_SIZE>
struct Path{
Point segment[MAX_SIZE];
};
但这不是我想要的(这只是MWE),所以我想知道如何重载复制赋值运算符以使其正常工作。我尝试了多种变体,例如:
template<size_t MAX_SIZE>
struct Path{
struct Point{
float x;
float y;
template<size_t OTHER_SIZE>
Point & operator = (const typename Path<OTHER_SIZE>::Point & that)
{
x = that.x;
y = that.y;
return *this;
}
};
Point segment[MAX_SIZE];
};
但我总是会遇到同样的错误。所以我的问题是:是否可以在不更改结构布局的情况下以允许以下形式赋值的方式重载=?
path_b.segment[0] = path_a.segment[0];
是的,这样的设置是可能的。核心是需要一个赋值运算符模板,该模板将接受所有类型:
template<class T>
Point & operator = (const T & that)
作为一个基本的解决方案,这就足够了。现在,它将与所有具有成员x
和y
兼容类型的类型一起使用,并为没有类型的类型产生(通常)难看的错误消息。
如果这对您足够好,我们已经完成。
如果赋值运算符还有其他重载,则可能需要有选择地禁用模板之一。为此,您将需要检测Point
类并使用SFINAE:
template<size_t MAX_SIZE>
struct Path{
struct Point{
float x;
float y;
struct EnableAssignment {};
};
Point segment[MAX_SIZE];
};
然后按以下方式使用检测:
template<class T, class U = typename T::EnableAssignment>
Point & operator = (const T & that)
上面的代码在函数模板中使用默认模板参数,该模板仅在C ++ 11中引入。在此之前,您将必须以其他方式调用SFINAE:
template <class L, class R>
struct SfinaeThenRight
{
typedef R type;
};
template <class T>
typename SfinaeThenRight<typename T::EnableAssignment, Point&>::type operator = (const T & that)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句