C++ semantic type wrapping
I have a data type for example class Vector3
. Now I need to create several classes with same interface as Vector3
, but with higher level semantic (for example: Position
, Velocity
). Using typedef
is not enough, because I need these types to be distinct so that they can be used for overloading. In C++0x I could probably use constructor inheritance:
struct Position: pub开发者_JS百科lic Vector3 {
using Vector3::Vector3;
};
Could there be any problems with this? Is there any better way to do it? Is it possible to do it without using C++0x features and not having to explicitly write all Vector3
constructors?
Consider using a tag struct
struct tagPosition {};
struct tagDirection {};
struct tagGeneric {};
namespace detail
{
template <typename Tag=tagGeneric>
class Vector3
{
// business as usual
};
}
typedef detail::Vector3<tagPosition> Position;
typedef detail::Vector3<tagDirection> Direction;
typedef detail::Vector3<tagGeneric> Vector3;
For bonus points, have conversion operators/constructors:
template <typename Tag=tagGeneric>
class Vector3
{
template <typename OtherTag>
explicit Vector3(const Vector3<OtherTag>& rhs) { /* ... */ }
// template <typename OtherTag>
// operator Vector3<OtherTag>() const { return /* ... */ }
};
If you like to live dangerously you can drop the explicit
keyword, or enable the implicit conversion operator. This would have the 'benefit' of being able to enable promiscuous operator resolutions like so:
Position pos;
Direction dir;
Generic gen;
dir = gen + pos; // you see why I call it 'promiscuous'?
I'd recommend (instead) to define explicit operators for cases like this (free functions:)
Position operator+(const Position& v, const Translation& d) { /* .... */ }
That way your class model reflects the semantics of your classes.
C++0x would possibly contain things to enable explicit conversion operators, IIRC:
In the case of converting constructors, you can disable implicit conversions by declaring the constructor as explicit The N1592 proposal stretches the semantics of this keyword to all conversion operators. A conversion operator declared explicit will not perform an implicit conversion. Instead, the programmer will have to call it explicitly
When I've needed distinct-but-similar types I've generally used a dummy template parameter, like (off the cuff, untouched by compiler's dirty hands)
template< class UniqueId >
struct Blah {};
typedef Blah< struct AlphaId > Alpha;
typedef Blah< struct BetaId > Beta;
This may or may not be what you need.
Cheers & hth.,
精彩评论