模板<类型名 T>贯穿整个代码

template <typename T> perculating all through the code

本文关键字:代码 lt 类型 模板 gt      更新时间:2023-10-16

我之前模板化了一个类,作为这个模板化的结果,所有接收这个新模板化类型的对象的类也需要模板化,即使模板化是完全不相关的。

:

  • class Shapeclass SphereCubeModel
  • 的基类
  • 每个Shape包含一个Mesh
  • Mesh现在已经被模板化,允许VertexBuffer基本上有一个参数化的类型:

:

template <typename T> struct Mesh
{
    VertexBuffer<T> verts ; // Mesh needs to be templated to allow
    // the vertex buffer to be templated as well
} ;

所以现在包含Mesh(基类Shape)的类也需要被模板化:

template <typename T> class Shape
{
    Mesh<T>* mesh ;
} ;

现在所有代码中的方法都需要被模板化以及,即使模板化不会影响代码(即代码与Mesh成员的顶点类型无关)

例如八叉树节点:

// An octree node
template <typename T> struct ONode // but this class doesn't really benefit
                                   // from templatization
{
    AABB bounds ;
    ONode* parent ; // facilitate movement thru the tree
    ONode* children[8]; // cells, octants, cubelets
    Shape<T>* objects ;    // for the purposes of the Octree,
                        // But ALL SHAPES BEHAVE THE SAME. <T> serves no purpose

这是一个非常讨厌的工件,我不确定如何在较早的时候停止模板化的循环,或者模板化是一个正确的选择,现在我看到有多少需要模板化。

我建议您为Mesh(或VertexBuffer,无论哪个最有意义)创建一个非模板化的基类,它公开不依赖于模板的功能,并在其他地方使用它。例如:

class MeshBase
{
    // Functionality that doesn't depend on the template type.
};
template<typename T>
class Mesh : public MeshBase
{
    // Functionality that does depend on the template type.
};

这确实意味着您可能更频繁地需要处理这种类型的动态分配值并将它们作为指针传递,但是明智地使用智能指针应该可以减轻这种负担。


一般来说,在使用面向对象原则和泛型编程原则之间存在一定的摩擦,其中一些您已经在这里发现了。无论何时发生这种情况,您本质上都需要一个能够保存多个泛型类型的值并对常见行为建模的类,而消费者无需知道模板化的类型。有时,即使类型没有公共基,也可以这样做。这种技术被称为类型擦除,Thomas Becker的这篇文章提供了一些关于这个问题的见解。