2016-03-23 13 views
2

Мне было интересно, как лучше всего получить доступ к параметру шаблона size_t, чтобы я мог передать его другому шаблону (а не вызову метода). Например, если у меня есть классы,Извлечение параметров шаблона 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; 
}; 

Я хочу, чтобы гарантировать, что метод пересекает в линии работает только для линии, пересекающей точку одних и тех же размеров (предотвратить 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

В C++ 11, вы можете обратиться

size_t dims() const {return D;} 

i Nto

static constexpr size_t dims() {return D;} 

И так

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

Второй не обрабатывает пример OP. –

+0

@ T.C .: Просто увидел это. – Jarod42

+0

Вам не нужно 'typename' перед' Point_t :: type'? –

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 

В принципе, я не считаю Точку быть форма. Если я это сделаю, мне не нужен класс Shape, чтобы знать D, и все, полученное из Shape, будет содержать Point_t, из которого я могу получить размеры. Мне просто нужно помнить о том, чтобы явно использовать методы пересечения для каждого класса, полученного из Shape, в класс Point.

Смежные вопросы