Reputation: 278
Imagine the following scenario where we have a pod container type that applies to many different scenarios:
struct vec2 {
float x, y;
};
Some of these scenarios might be storing a velocity, a position, an acceleration, etc. Now suppose we want to be able to handle all these scenarios independently while putting the type system to work and also maintaining the semantics of vec2
, i.e. velocity.x
, acceleration.y
, etc.:
struct Simulation {
template<typename T>
static void handle() { fprintf( stdout, "Generic handler\n" ); }
};
template<>
void Simulation::handle<vec2>() { fprintf( stdout, "generic vec2 handler\n" ); }
template<>
void Simulation::handle<position>() { fprintf( stdout, "position handler\n" ); }
template<>
void Simulation::handle<velocity>() { fprintf( stdout, "velocity handler\n" ); }
template<>
void Simulation::handle<acceleration>() { fprintf( stdout, "acceleration handler\n" ); }
In the above case using either typedef
or using
will not do the job as they do not affect the typeid of the alias as per the standard, so one cannot do:
using position = vec2;
The next attempt might be to try and inherit from the pod, i.e.:
struct position : public vec2 {}
however this has the disadvantage that new
and delete
are now broken as there is no virtual destructor on the pod type, and also the qualification of the position
being a pod has been lost due to the inheritance.
Then it could be argued that simply copying and pasting the code for vec2
and renaming it to the desired type would satisfy all the requirement, but there are also a couple of issues with this:
The vec2 could also be encapsulated in the new type:
struct position {
vec2 pos;
};
but this solution breaks the requirement for maintaining the semantics.
Another thing to note is that we might not have control over the implementation of vec2 (i.e. in the case where a library like GLM is used).
I feel that templating should provide the necessary solution, but can't work out how it would work. So the question is what is the correct way of going about redefining a type, while maintaining the semantics of the type, but ending up with a different type id?
*-not in all scenarios, but this one definitely
Upvotes: 0
Views: 50
Reputation: 42926
You can define vec2
as a template class and use an enum flag to represent its storage type.
enum class data_type {
position, velocity, acceleration
};
template<data_type>
struct vec2 {
float x, y;
};
vec2<data_type::position> p;
vec2<data_type::velocity> v;
vec2<data_type::acceleration> a;
Upvotes: 0
Reputation: 52611
Something along these lines, perhaps.
template <typename Tag>
struct vec2 {
float x, y;
};
using position = vec2<struct PositionTag>;
using velocity = vec2<struct VelocityTag>;
position
and velocity
would have similar behavior, but are distinct types.
Upvotes: 3