我想知道访问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;
答案 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类。