I want a class template template<std::size_t N> Shape
, where the template parameter N
represents the dimension of the Shape
. There should be a limited number of predefined Shape
s, such as Shape<2> SQUARE
, Shape<3> CUBE
and Shape<3> SPHERE
. I might add more predefined Shape
s in the future.
I want Shape
objects only to be constructible as any of the predefined Shape
s. Since the properties of these predefined Shape
s 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.
At this moment, I have the following implementation:
// 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}});
This implementation has a few problems:
Shape
contains all the predefined Shape
s (As pointed out in the comments of this question);Shape
that is created, the content of the predefined Shape
s gets copied;Shape<3>
object contains the Shape<2> SQUARE
.I would like to know what would be a better design pattern to achieve the above described goals.
I was thinking of using the Tag
as a constructor parameter and using some kind of factory. However, I have problems to get the implementation details right due to the template complications and the fact that I only want predefined Shape
s to be constructible.
Factory pattern is what you need. It delegates the creation of the instances to another class.
There are multiple way to implement it, you can choose the level of abstraction depending on the complexity of your problem.
Here's a basic example
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.
if you strictly want to use this approach, you can refer to Prototype Pattern