Нужно ли специализировать весь класс, когда отличается только несколько членов? - PullRequest
2 голосов
/ 01 августа 2011

Я разрабатываю класс, который практически одинаков для 2d и 3d, поэтому я пытаюсь использовать шаблоны, чтобы создать его как один класс, типизированный векторным типом (2d od 3d)

Некоторые методы и члены очень похожи для 2D и 3D

Некоторые (но очень немногие) методы немного отличаются, я использую черту здесь - см. doSomething()

Некоторые члены и метод присутствуют для 3d, но не для 2d (вектор вверх) и ЭТО МОЯ ПРОБЛЕМА.

Я могу решить эту проблему путем полной специализации класса, но есть ли другой способ, как включить / исключить эти члены без специализации всего класса?

У меня есть черта:

template<typename T>
struct VectorInfo{};

template<>
struct VectorInfo<Vec2>
{
    enum { dim = 2 };
};

template<>
struct VectorInfo<Vec3>
{
    enum { dim = 3 };
};

template<int Val>
struct VectorDimension
{
    enum { val = Val };
};

и класс:

template <typename vector_type>
class LocalSpace
{
public:
    ////////////////////////////////////////
    //Common for 2D and 3D
    const vector_type & getSideVector() const;      
    void setSideVector(const vector_type & s);

    const vector_type & getForwardVector() const;
    void setForwardVector(const vector_type & f);

    const vector_type & getPosition() const;
    void setPosition(const vector_type & p);

    bool isRightHanded() const;

    //others methods...

    //////////////////////////////////////////
    //only for 3D
    const vector_type & getUpVector() const;    
    void setUpVector(const vector_type & u);   

    //One of few methods differing for 2D and 3D 
    inline void doSomething(const vector_type & v)      
    {
        doSomethingImpl(v, VectorDimension<VectorInfo<vector_type>::dim>);
    }

protected:

    void doSomethingImpl(const vector_type & v, VectorDimension<2>)
    {
    }

    void doSomethingImpl(const vector_type & v, VectorDimension<3>)
    {
    }

private:
    vector_type m_side;     //2d+3d        
    vector_type m_forward;  //2d+3d
    vector_type m_up;       //3d ONLY

    vector_type m_position; //2d+3d
};

Надеюсь, вы понимаете мой вопрос.

EDIT: Спасибо за ваши ответы, теперь у меня есть

struct BlankType{};

template <typename vector_type>
class LocapSpace3DBase
{
public:
    const vector_type & getUpVector() const;
    void setUpVector(const vector_type & u);
private:
    vector_type m_up;
};

template <typename vector_type>
class LocalSpace : public boost::mpl::if_c<
                                                            VectorInfo<vector_type>::dim == 3,
                                                            LocapSpace3DBase<vector_type>,
                                                            BlankType>::type

Есть ли способ избавиться от BlankType? Например, если размерность равна 3, производная от 3DBase, если нет, НИЧЕГО (вместо производной от пустой структуры)?

Ответы [ 3 ]

3 голосов
/ 01 августа 2011

Вы можете наследовать от различных базовых классов, используя mpl :: if_ или mpl :: if_c .В ветке для 3d вы можете объявить члены и методы, необходимые только для случая 3d.

Примерно так:

class LocalSpaceBase2
{
    vector_type m_up;
    // ...
};

template <typename vectortype>
class LocalSpace : public boost::mpl::if_c<
                              boost::is_same<vectortype, Vec3>,
                              LocalSpaceBase3,
                              LocalSpaceBase2>::type
{
    ...
1 голос
/ 01 августа 2011

boost::enable_if<> предназначен только для подобных случаев.

0 голосов
/ 01 августа 2011

Да: если вы специализируете шаблон, вы должны специализировать весь шаблон.

Однако есть более простое решение: просто поместите все элементы, даже 3-мерные, в основной шаблон, а затем добавьте static_assert s к 3-мерным элементам, чтобы убедиться, что они используются только. для трехмерного вектора.

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

...