类模板实例仅限于预定义对象

时间:2018-10-15 09:37:03

标签: object templates c++14 template-specialization predefined-variables

我想要一个类模板template<std::size_t N> Shape,其中模板参数N代表Shape的尺寸。应该有数量有限的预定义Shape,例如Shape<2> SQUAREShape<3> CUBEShape<3> SPHERE。我将来可能会添加更多预定义的Shape

我希望Shape对象只能像任何预定义的Shape一样构造。由于这些预定义的Shape的属性始终保持不变,因此最好将它们仅存储一次,并让新的Shape对象引用它们。

此刻,我有以下实现:

// Flag for the possible shapes
enum class Tag
{
    SPHERE,
    CUBE,
    SQUARE
};

template<std::size_t N>
class Shape
{
public:
    // Predefined shapes.
    static const Shape<3> SPHERE;
    static const Shape<3> CUBE;
    static const Shape<2> SQUARE;
    // Information stored about the given shapes
    const Tag tag; // tag specifying the shape
    const double v; // Shape volume/area
    const std::array<double, 2*N> surrounding_box; // Storing intervals for a surrounding box
    //... Some other information that depends on template parameter N
private:
    // Private constructor. This prevents other, unintended shapes from being created
    Shape(Tag tag, double v, const std::array<double, 2*N> surrounding_box):
            tag{tag}, v {v}, surrounding_box {surrounding_box} {};
};

// Initialization of predefined shape: SPHERE
template<std::size_t N>
const Shape<3> Shape<N>::SPHERE(Tag::SPHERE, 3.0,{{0.0,2.7,0.0,2.7,0.0,2.7}});

// Initialization of predefined shape: CUBE
template<std::size_t N>
const Shape<3> Shape<N>::CUBE(Tag::CUBE, 1.0,{{0.0,1.0,0.0,1.0,0.0,1.0}});

// Initialization of predefined shape: SQUARE
template<std::size_t N>
const Shape<2> Shape<N>::SQUARE(Tag::SQUARE, 1.0,{{0.0,1.0,0.0,1.0}});

此实现存在一些问题:

  • Shape的每个实例都包含所有预定义的Shape(如this question的注释中所述);
  • 对于创建的Shape的每个实例,都将复制预定义的Shape的内容;
  • 即使一个Shape<3>对象也包含Shape<2> SQUARE
  • ...

我想知道哪种更好的设计模式来实现上述目标。 我当时在考虑使用Tag作为构造函数参数,并使用某种工厂。但是,由于模板的复杂性以及我只希望预定义的Shape是可构造的,因此我难以正确地实现实现细节。

1 个答案:

答案 0 :(得分:1)

工厂模式是您所需要的。它将实例的创建委托给另一个类。

有多种实现方式,您可以根据问题的复杂程度选择抽象级别。

这是一个基本示例

template<std::size_t N>
class Shape
{
    friend class ShapeFactory;
public:
    // Information stored about the given shapes
    const Tag tag; // tag specifying the shape
    const double v; // Shape volume/area
    const std::array<double, 2*N> surrounding_box; // Storing intervals for a surrounding box
    //... Some other information that depends on template parameter N
private:
    // Private constructor. This prevents other, unintended shapes from being created
    Shape(Tag tag, double v, const std::array<double, 2*N> surrounding_box):
            tag{tag}, v {v}, surrounding_box {surrounding_box} {};
};

class ShapeFactory
{
public:
    // return value optimization
    static Shape<3> createSphere()
    {
        return Shape<3>(Tag::SPHERE, 3.0,{{0.0,2.7,0.0,2.7,0.0,2.7}});
    }

    static Shape<3> createCube()
    {
        return Shape<3>(Tag::CUBE, 1.0,{{0.0,1.0,0.0,1.0,0.0,1.0}});
    }

    static Shape<2> createSquare()
    {
        return Shape<2>(Tag::SQUARE, 1.0,{{0.0,1.0,0.0,1.0}});
    }
};
  

由于这些预定义形状的属性完全相同   时间,最好只将它们存储一次,并具有   新的Shape对象引用了它们。

如果您严格希望使用此方法,则可以参考原型模式