2013-07-12 2 views
3

я получил следующее:C++: Расширение класса шаблон

template<typename T> class CVector3 
{ 
    CVector3<T> &normalize(); 
    // more stuff 
}; 

typedef CVector3<float> Vector3f; 
typedef CVector3<double> Vector3d; 

Я в принципе хочу добавить метод, toPoint(), который возвращает STRUCT Point3f, если T = поплавок и структура Point3d, если T = двойная. Я попытался заменить два определений типов с:

class Vector3f: public CVector3<float> 
{ 
    Point3f toPoint() const; 
}; 

class Vector3d: public CVector3<double> 
{ 
    Point3d toPoint() const; 
}; 

Это не работает, однако, потому что теперь нормализуют() не нарушается: он больше не возвращается Vector3f, но CVector3 < поплавок >, что несовместимо с Vector3f, потому что это, по сути, базовый класс. Я мог бы добавить методы-оболочки для normalize() и любого другого общедоступного метода в базовом классе, но я не хочу этого делать, потому что это сделало бы сохранение этих классов утомительным.

Я также попытался сдачи обратно определений типов и добавление вне определения шаблона:

template<> 
Point3f CVector3<float>::toPoint() const; 

template<> 
Point3d CVector3<double>::toPoint() const; 

Это не компилируется, потому что toPoint() не объявлен в определении шаблона. Я не могу поместить его внутри, из-за возвращаемого типа Point3f/Point3d.

Как это сделать? Любая помощь очень ценится!

+0

Являются ли 'Point3f/Point3d' instantiad шаблонами? – jrok

+0

нет, они простые структуры. –

+0

Возможно, CRTP ...? –

ответ

0

Благодаря вашим ответам, я теперь понял, способ, который должен работать:

template<typename T, typename P> class CVector3 
{ 
    CVector3<T, P> &normalize(); 
    // more stuff 

    P toPoint() const; 
}; 

typedef CVector3<float, Point3f> Vector3f; 
typedef CVector3<double, Point3d> Vector3d; 

Я собираюсь попробовать это и скажите, если это сработает позже. Ура!

EDIT: Да, это сработало! Я должен был определить toPoint(), как это:

template<> 
Point3f CVector3<float, Point3f>::toPoint() const 
{ 
    Point3f pt = { x, y, z }; 
    return pt; 
} 

Ваши ответы с чертами, безусловно, более общее решение, но так как Point3f естественный кулон для Vector3f, я как второй параметр шаблона лучше.

3

Вы можете использовать класс вспомогательного стиля стиля.

template<typename T> CVectorTraits {}; 
template<> CVectorTraits<double> { typedef Point3d PointType; } 
template<> CVectorTraits<float> { typedef Point3f PointType; } 

template<typename T> class CVector3 
{ 
    CVector3<T> &normalize(); 
    // more stuff 
    typename CVectorTraits<T>::PointType toPoint() const; 
}; 
+0

спасибо! это, вероятно, общее решение. пытаясь понять, это привело меня к другому решению, которое хорошо работает в моем случае и немного проще, см. ниже. –

1

Вы можете использовать черты типа:

template<typename T> 
struct VectorTraits; 

template<> 
struct VectorTraits<float> { 
    typedef Point3f Point; 
}; 
template<> 
struct VectorTraits<double> { 
    typedef Point3d Point; 
}; 

template<typename T> class CVector3 
{ 
    CVector3<T> &normalize(); 

    typename VectorTraits<T>::Point 
    toPoint() const; 

    // more stuff 
}; 

typedef CVector3<float> Vector3f; 
typedef CVector3<double> Vector3d; 
+0

спасибо!это, вероятно, общее решение. пытаясь понять, это привело меня к другому решению, которое хорошо работает в моем случае и немного проще, см. ниже. –

0

Вы можете улучшить синтаксис для клиентов и применять ограничение для обеспечения того, чтобы клиенты не получали аргументы шаблона неправильно, используя специализацию.

struct Point3f { float x, y, z; }; 
struct Point3d { double x, y, z; }; 

// Base template toPoint returns Point3f. 
template<typename T, typename U = Point3f> 
class Vector3 
{ 
public: 
    Vector3& normalize(){ return Vector3(); } 
    U toPoint(){ return Point3f(); } 
}; 

// Specialization for double, toPoint returns Point3d. 
template<> 
class Vector3<double> 
{ 
public: 
    Vector3& normalize(){ return Vector3(); } 
    Point3d toPoint(){ return Point3d(); } 
}; 


TEST(TemplateTests2, Test3) 
{ 
    Vector3<float> v1; 
    Point3f p1 = v1.toPoint(); 

    Vector3<double> v2; 
    Point3d p2 = v2.toPoint(); 
} 
+0

спасибо за предложение. в моем случае «клиенты» должны использовать только typedefs Vector3f и Vector3d, у которых уже установлены правильные комбинации. –

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

  • Нет связанных вопросов^_^