Class 模板实例限于预定义对象

Class template instances limited to predefined objects

我想要一个 class 模板 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}});

这个实现有一些问题:

我想知道实现上述目标的更好设计模式是什么。 我正在考虑使用 Tag 作为构造函数参数并使用某种工厂。但是,由于模板的复杂性以及我只希望预定义的 Shape 是可构造的这一事实,我无法正确获取实现细节。

工厂模式就是你所需要的。它将实例的创建委托给另一个 class.

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

这是一个基本示例

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}});
    }
};

Since the properties of these predefined Shapes remain the same at all time, it would be optimal to have them stored only once, and to have new Shape objects refer to them.

如果你确实想使用这种方法,你可以参考原型模式