是否有必要专门化全班,只有少数成员不同?

时间:2011-08-01 16:22:48

标签: c++ templates metaprogramming traits

我正在设计类,对于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
};

希望你理解我的问题。

修改 谢谢您的反馈, 现在我有

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 个答案:

答案 0 :(得分:3)

您可以使用mpl::if_mpl::if_c从不同的基类派生。在3d分支中,您可以声明仅需要3d case的成员和方法。

这样的事情:

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 :(得分:1)

boost::enable_if<>仅适用于此类案例。

答案 2 :(得分:0)

是:如果您专门化模板,则必须专门化整个模板。

但是,有一个更简单的解决方案:只需将所有成员(甚至是3-D特定成员)放入主模板,然后将static_assert添加到3-D特定成员,以确保它们是仅用于三维矢量。

这不是一个特别可扩展的解决方案,但如果您只有一个或两个专业化,那么它很简单,如果您需要更多的灵活性,以后重构很简单。