提取size_t模板参数

时间:2016-03-23 17:45:22

标签: c++ templates

我想知道访问size_t模板参数的最佳方法是什么,这样我就可以将它传递给另一个模板化的类(所以不能通过方法调用)。例如,如果我有课程,

template<typename T, size_t D> class Point;
template<typename T> class Line;

template<typename T, size_t D>
class Shape
{
  public:
   virtual size_t dims() const = 0;
   virtual bool intersects(Point<T,D> p) const  = 0;
   virtual bool intersects(Line<Point<T,D>> l) const = 0;
}

template<typename T, size_t D>
class Point : Shape<T,D>
{
  public:
   typedef T type;
   size_t dims() const {return D;}
   type val(size_t d) {return vals[d];}
   bool intersects(Point<T,D> p)
   {
     for(size_t d=0; d<D; ++d) if(p.vals[d] != vals[d]) return false;
     return true;
   }     

   bool intersects(Line<Point<T,D>> l)
   {
     return l.intersects(*this);
   }  

  protected:
   type vals[D];
};

// How do I get D???
template<typename Point_t>
class Line : public Shape<typename Point_t::type,??>
{
  public:
   typedef typename Point_t::type type;
   size_t dims() const {return point.dims();}

   bool intersects(Point<type,??> p) {/*stuff*/}      
   bool intersects(Line<Point_t> l) {/*stuff*/}

  private:
   Point_t point;
   type slope;
};

我想确保Line ONLY中的intersects方法适用于与相同尺寸的点相交的线(防止3D线与2D点相交)。我想让Line使用与Point相同的参数,但是编译器不会捕获错误,例如将笛卡尔定义的线与球面定义的点相交(因为两者都是Point<double,3>)。根据我的上述情况,我可以定义笛卡尔和球形类来避免这个问题。

 template<typename T, size_t D> class Cartesian : public Point<T,D>{/*stuff*/}
 template<typename T> class Spherical : public Point<T,3> {/*stuff*/}

 Line<Cartesian<double,3>> Line;
 Cartesian<double,3> C3Point;
 Cartesian<double,2> C2Point;
 Spherical<double> SPoint;
 Line.intersects(C3Point); // ok
 Line.intersects(C2Point); // compiler error
 Line.intersects(SPoint); // compiler error

编辑: 我目前所做的是将Line类定义为

template<typename Point_t, size_t D>
class Line : public Shape<typename Point_t::type,D>
{/*stuff*/}

有效,但包含冗余信息......

 Line<Cartesian<double,3>,3> Line;

2 个答案:

答案 0 :(得分:2)

在C ++ 11中,你可以转向

size_t dims() const {return D;}

static constexpr size_t dims() {return D;}

所以

template<typename Point_t>
class Line : public Shape<typename Point_t::type, Point_t::dims()> {..};

答案 1 :(得分:0)

我想我明白了。我的实际代码比示例更复杂(这就是为什么我认为看到解决方案更难),但这种基本方法有效。我重新组织了我的课程,如下所示,

template<typename T> class Line;

template<typename T, size_t D>
class Point
{
  public:
   typedef T type;
   size_t dims() const {return D;}
   type val(size_t d) {return vals[d];}
   bool intersects(Point<T,D> p)
   {
     for(size_t d=0; d<D; ++d) if(p.vals[d] != vals[d]) return false;
     return true;
   }     

   bool intersects(Line<Point<T,D>> l)
   {
     return l.intersects(*this);
   }  

  protected:
   type vals[D];
};

template<typename T>
class Shape
{
  public:
   typedef T Point_t;
   virtual size_t dims() const = 0;
   virtual bool intersects(Point_t p) const  = 0;
   virtual bool intersects(Line<Point_t> l) const = 0;
}

template<typename Point_t>
class Line : public Shape<Point_t>
{
  public:
   typedef typename Point_t::type type;
   size_t dims() const {return point.dims();}

   bool intersects(Point_t p) {/*stuff*/}      
   bool intersects(Line<Point_t> l) {/*stuff*/}

  private:
   Point_t point;
   type slope;
};

现在以下工作正常,

 template<typename T, size_t D> class Cartesian : public Point<T,D>{/*stuff*/}
 typedef Cartesian<double,3> Cartesian3D;
 typedef Cartesian<double,2> Cartesian2D;
 template<typename T> class Spherical : public Point<T,3> {/*stuff*/}

 Line<Cartesian3D> Line;
 Cartesian3D CPoint3D;
 Cartesian2D CPoint2D;
 Spherical<double> SPoint;
 Line.intersects(C3Point); // ok
 Line.intersects(C2Point); // compiler error
 Line.intersects(SPoint); // compiler error

基本上,我不认为Point是一个Shape。如果我这样做,我不需要Shape类来知道D,并且从Shape派生的所有东西都将包含一个Point_t,我可以从中获取尺寸。我只需要记住明确地将从Shape派生的每个Class的交集方法放入Point类。