I'm currently writing a small generic library for placing objects in a scene. The arrangement of the objects should be decided depending on the bounding box of the contents of the object. The class currently looks something like this:
template<class T>
class Object {
public:
Object() = default;
Object(const T& content, const Rect& bounding_box)
: _content(content)
, _bounding_box(bounding_box) {}
private:
T _content;
Rect _bounding_box;
};
Now, to construct the object we need to know the bounding box. Naturally it depends on the type T
of the contents and might be quite complex to calculate (i.e. text).
My idea was that the user should supply its own Measurer
which performs this calculation for his own content. An object could then be created by:
template <class T, class Measurer>
Object create_label(const T& value, Measurer op)
{
return Object(value, op(value));
}
Should this method be somehow incorporated into the Object
class (something like a policy)? I was thinking something similar to allocators in the STL. Is there a generic design pattern for this kind of problem and how would you write such a class?
Also, should the constructor Object(const T& content, const Rect& bounding_box)
be marked as protected
, so that the user is pointed to the create_label
method?
I think you want to look at static member functions. This type of method doesn't require (or have) an object to operate on so it is more like a global function BUT it has scope and visibility like a class method.
Factory methods such as your createLabel are typically declared within the class something like:
class Object {
public:
static Object createLabel(...);
}
Now because this is a static method you can call it directly without an instance:
Object O=Object.createLabel(...);
If you want to follow this strategy then your constructors SHOULD be private or protected to stop class users instantiating them directly. (BTW this works equally well for templated classes like yours)
There are various other strategies you might use to solve your particular problem which might be more convenient depending on your situation:
EDIT: At OP's request some ideas on the partial template solution: The most direct way it to simply declare a function inside the template definition like so
template<class T>
class Object {
.....
private:
BoundingBox measureMe();
}
Now as there is no *definition& supplied for measureMe (above is a declaration) any instantiated instamce of Object is going to cause a linker error as no MeasureMe() is defined.
But you supply specific implementations for specific types, so you can include definitions for various specific types:
BoundingBox Object<MyThing1>::measureMe()
{
... calculatethe size of a MyThing1
}
BoundingBox Object<MyThing2>::measureMe()
{
... calculate the size of a MyThing2
}
Now if you try to instantiate a object types for which you haven't defined a measureme on you still get an error; but the known types work as you wish.
Remember that you CAN still define a generic templated version of this function which will be used if there is no more specific version available which might be useful for you if most of your cases use the same logic but there are a few edge exceptions.