展平/重构某些输入的C ++模板源

时间:2013-09-26 09:40:53

标签: c++ templates refactoring code-generation

我有一些我正在尝试重构的模板代码。具体来说,它是一种几何类型,由参数维度模板化(因此它可以表示曲线,曲面,体积,超体积等),以及点类型。

问题在于以这种通用方式进行编辑变得非常笨拙,而且大多数时候我们只使用参数化维度1,2和3.部分特化是这些日子里唯一改变的事情,共享代码非常稳定和完整。

除了编辑代码的困难之外,还存在一些性能问题,这些问题源于必须以推广到任意维度的网格的方式存储内部数据。有可能减轻通用中的性能问题方式,但这将继续增加许多不必要的复杂性。基本上问题是模板过于笼统。

所以,我将用3个独立的模板替换通用模板代码,每个模块一个。我还想保留点类型的模板,所以我不想只使用普通类。

如果我多次使用宏和#including文件模拟C方式,我可以通过预处理器运行输入并获得我想要的3个不同版本。

虽然我可以手工完成,但我更喜欢自动化解决方案,至少作为起点。

C ++是否存在任何类似的方法或重构解决方案,以获取具有特定输入的模板的来源?


为了更具体一点,我有这样的代码:

template< int Dimension, class PointType > class Nurbs { ... }
template< class PointType > class NurbsCurve : public Nurbs< 1, PointType > { ... }
template< class PointType > class NurbsSurface : public Nurbs< 2, PointType > { ... }
template< class PointType > class NurbsVolume : public Nurbs< 3, PointType > { ... }

但我希望最终得到这样的代码:

template< class PointType > class NurbsCurve { ... }
template< class PointType > class NurbsSurface { ... }
template< class PointType > class NurbsVolume { ... }

2 个答案:

答案 0 :(得分:0)

这并没有真正回答你的问题,但它是另一种保留模板化代码的方法。

如果我理解正确,你的代码有很多专业化,它变得笨拙。处理此问题的一种方法是使用一些帮助程序模板类处理所有细节,并从其他模板调用其静态成员。辅助类将有一个实现泛型(与维度无关的代码)的基础,然后将有专门化,只覆盖需要为特定维度重写的任何内容。

namespace details {
  template<int Dimension> struct helper_base  // generic code
  {
    static_assert(Dimension>1,"missing specialisation Dimension=0,1");
    static const int Last = Dimension-1;

    template<typename T>
    static T dot_product(const T*a, const T*b) noexcept
    { return helper<Last>::dot_product(a,b) + a[Last]*b[Last]; }
  };

  template<> struct helper_base<1>
  {
    template<typename T>
    static T dot_product(const T*a, const T*b) noexcept
    { return a[0]*b[0]; }
  };

  template<int Dimension> struct helper // special code for certain dimensions
    : helper_base<Dimension> {};
  template<> struct helper<3> : helper_base<3>
  {
    // any code that is particular to 3D.
    template<typename T>
    static void cross_product(T*p, const T*x, const T*y) noexcept
    {
      p[0] = x[1]*y[2] - x[2]*y[1];
      p[1] = x[2]*y[0] - x[0]*y[2];
      p[2] = x[0]*y[1] - x[1]*y[0];
    }
  };
}

template<typename T, int Dimension>
struct point
{
   using helper = details::helper<Dimension>;
   T X[Dimension];  // for instance
   T operator*(point const&x) const noexcept { return helper::dot_product(X,x.X); }
   // etc.
};

template<typename T>
point<T,3> operator^(point<T,3> const&x, point<T,3> const&y) noexcept
{
  point<T,3> result;
  details::helper<3>::cross_product(result.X,x.X,y.X);
  return result;
}

答案 1 :(得分:0)

不确定它是否回答了您的问题:

您可以删除继承,并使用成员,而不是:

template<class PointType> class NurbsCurve   : public Nurbs<1, PointType> { ... };
template<class PointType> class NurbsSurface : public Nurbs<2, PointType> { ... };
template<class PointType> class NurbsVolume  : public Nurbs<3, PointType> { ... };

使用类似:

template<class PointType> class NurbsCurve   { ... private: Nurbs<1, PointType> data; };
template<class PointType> class NurbsSurface { ... private: Nurbs<2, PointType> data; };
template<class PointType> class NurbsVolume  { ... private: Nurbs<3, PointType> data; };

注意: - 您可能需要在每个班级复制Nurbs的原型。 - 如果需要,稍后您可以通过特定实现替换Nurbs。