我正在设计代表矢量等几何对象的类。我需要定义诸如加法,标量乘法,点积和其他方法。向量坐标可以是不同大小的整数或实数,因此需要复制对应于这些不同类型的类。
例如
class intVector
{
int X, Y;
intVector& operator+=(const intVector& A) { … }
intVector& operator*=(int A) { … }
float Norm(); // Not int
};
class floatVector
{
float X, Y;
floatVector& operator+=(const floatVector& A) { … }
floatVector& operator*=(float A) { … }
float Norm(); // Would be double for a doubleVector
};
(我还需要将二进制运算符定义为函数而不是方法。)
我想避免/减少代码重复,因此使用模板似乎是一种自然的方法。无论如何,我希望我的类显示为普通类,而不是模板化类(一种选择是从模板化类派生;另一种是typedef类专业化)。
此外,还有一个讨厌的约束:并非所有方法对所有数据类型都有意义,并且某些类中的所有方法都不应该完全声明,否则某些参数的类型可能会有特殊情况。
在尝试过程中,我遇到了许多问题,例如需要添加许多显式的实例化,难以避免没有意义的成员,在基类/派生类之间转换问题……使整个设计痛苦不堪。总而言之,与没有模板相比,我用模板编写的代码更多!
您经历过类似的课堂设计吗?有经典的解决方法吗?
答案 0 :(得分:1)
模板是处理此问题的正确方法。您可以做的是为需要以不同方式运行的不同函数添加重载,并使用SFINAE将重载约束为所需的类型。使用模板,我们可以将两个类组合成一个通用的Vector
类,然后使用type alias来获取不同类型的具体名称。看起来像
template<typename T>
class Vector
{
T X, Y;
Vector& operator+=(const Vector& A) { … }
Vector& operator*=(T A) { … }
template<typename U = T, std::enable_if_t<std::is_integral_v<U>, bool> = true>
correct_size_floating_point_type<U> Norm() { integer code }
template<typename U = T, std::enable_if_t<std::is_floating_point_v<U>, bool> = true>
U Norm() { floating point code }
};
using intVector = Vector<int>;
using floatVector = Vector<float>;
correct_size_floating_point_type
是一种模板类型,它为提供的整数类型返回正确大小的浮点类型。