关于c ++:当只有很少的成员时,有必要专门研究整个类吗?

Is it necessary to specialize whole class, when differs just with few members?

我正在设计类,这对于2d和3d几乎是相同的,所以我尝试使用模板,以将其创建为按矢量类型(2d od 3d)键入的一个类。

2d和3d的某些方法和成员非常相同

一些(但很少)方法略有不同,我在这里使用特征-请参见doSomething()

有些成员和方法适用于3d,但不适用于2d(向上矢量),这是我的问题。

我可以通过完全的类专门化来解决它,但是还有其他方法,如何在不专门化整个类的情况下包括/排除这些成员?

我有特质:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 };
};

和班级:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
};

希望你理解我的问题。

编辑:
谢谢您的反馈,
我现在有

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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派生,如果不是,则不做(而不是从空结构派生)?


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

像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
class LocalSpaceBase2
{
    vector_type m_up;
    // ...
};

template <typename vectortype>
class LocalSpace : public boost::mpl::if_c<
                              boost::is_same<vectortype, Vec3>,
                              LocalSpaceBase3,
                              LocalSpaceBase2>::type
{
    ...


boost::enable_if<>专为此类情况设计。


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

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

这不是一个特别可伸缩的解决方案,但是如果您只有一个或两个专业,那么它很简单,并且如果需要更大的灵活性,以后可以很容易地进行重构。