C++:扩展一个模板类
C++: Extending a template class
我得到了以下内容:
template<typename T> class CVector3
{
CVector3<T> &normalize();
// more stuff
};
typedef CVector3<float> Vector3f;
typedef CVector3<double> Vector3d;
我基本上想添加一个方法,toPoint(),如果T=float,它会返回一个结构体Point3f,如果T=double,它会输出一个结构物Point3d。我试着用替换这两个typedef
class Vector3f: public CVector3<float>
{
Point3f toPoint() const;
};
class Vector3d: public CVector3<double>
{
Point3d toPoint() const;
};
然而,这不起作用,因为现在normalize()被破坏了:它不再返回Vector3f,而是返回CVector3<float>,它与Vector3f不兼容,因为它实际上是基类。我可以在基类中添加normalize()的包装器方法和任何其他公共方法,但我不想这样做,因为这会使维护这些类变得乏味。
我还尝试将typedefs放回模板中,并在模板定义之外添加:
template<>
Point3f CVector3<float>::toPoint() const;
template<>
Point3d CVector3<double>::toPoint() const;
这不会编译,因为toPoint()没有在模板定义中声明。我不能把它放在里面,因为返回类型是Point3f/Point3d。
我该怎么做?非常感谢您的帮助!
您可以使用traits样式的辅助类。
template<typename T> CVectorTraits {};
template<> CVectorTraits<double> { typedef Point3d PointType; }
template<> CVectorTraits<float> { typedef Point3f PointType; }
template<typename T> class CVector3
{
CVector3<T> &normalize();
// more stuff
typename CVectorTraits<T>::PointType toPoint() const;
};
您可以使用类型特征:
template<typename T>
struct VectorTraits;
template<>
struct VectorTraits<float> {
typedef Point3f Point;
};
template<>
struct VectorTraits<double> {
typedef Point3d Point;
};
template<typename T> class CVector3
{
CVector3<T> &normalize();
typename VectorTraits<T>::Point
toPoint() const;
// more stuff
};
typedef CVector3<float> Vector3f;
typedef CVector3<double> Vector3d;
感谢您的回复,我现在已经找到了一种可行的方法:
template<typename T, typename P> class CVector3
{
CVector3<T, P> &normalize();
// more stuff
P toPoint() const;
};
typedef CVector3<float, Point3f> Vector3f;
typedef CVector3<double, Point3d> Vector3d;
我会试试这个,稍后告诉你它是否有效。干杯
编辑:是的,成功了!我不得不这样定义toPoint():
template<>
Point3f CVector3<float, Point3f>::toPoint() const
{
Point3f pt = { x, y, z };
return pt;
}
你的带有特征的答案当然是一个更通用的解决方案,但由于Point3f是Vector3f的自然吊坠,我更喜欢第二个模板参数。
您可以改进客户端的语法,并强制执行约束,以确保客户端不会通过使用专门化来获得错误的模板参数。
struct Point3f { float x, y, z; };
struct Point3d { double x, y, z; };
// Base template toPoint returns Point3f.
template<typename T, typename U = Point3f>
class Vector3
{
public:
Vector3& normalize(){ return Vector3(); }
U toPoint(){ return Point3f(); }
};
// Specialization for double, toPoint returns Point3d.
template<>
class Vector3<double>
{
public:
Vector3& normalize(){ return Vector3(); }
Point3d toPoint(){ return Point3d(); }
};
TEST(TemplateTests2, Test3)
{
Vector3<float> v1;
Point3f p1 = v1.toPoint();
Vector3<double> v2;
Point3d p2 = v2.toPoint();
}
相关文章:
- 基于范围的 for 循环:迭代使用一个元素扩展的向量
- 我想通过带有C++和Python的插件创建一个可扩展的应用程序
- 如何构建一个 setup.py 来编译C++使用 Python、pybind11 和 Mingw-w64 的扩展?
- 为什么 MSVC C++编译器将一个简单的 Hello World 扩展为 4000 行汇编?
- 在另一个字符串中插入文件扩展名之前的字符串
- 如何将一个 QQuickItem 扩展作为子扩展添加到另一个 QQuickItem 扩展?
- 将 int 转换为字符串,然后连接另一个变量以创建完整扩展名,然后将其转换为 const_char*
- RXCPP:创建一个不关心可观察量输入类型的扩展
- 是否可以在不扩展初始宏的情况下将一个宏作为参数提供给另一个宏?
- 用一个额外的元素扩展 std::array 的每个 std::元组
- 如何使用直接IO编写一个带有扩展文件大小的小文件
- 如何将矢量大小扩展一个元素并用变量填充它
- 设计一个扩展良好的多线程应用程序
- 通过在上一个数组结束后立即存储下一个元素来扩展数组
- 为什么我不能在 c++ 类中声明一个空构造函数,该构造函数从一个具有私有构造函数的构造函数扩展而来
- Qt多个文件过滤器,强制一个扩展名
- GLEW只是一个扩展库,或者它也包含OpenGL ES 2.0实现
- 可变长度数组也是Clang中的一个扩展吗
- 如何为Internet Explorer创建一个扩展作为Exe-Com服务器
- 写入一个扩展名不同但名称与所读文件相同的文件