Подумайте об использовании тега 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;
Для бонусных баллов есть операторы / конструкторы преобразования:
template <typename Tag=tagGeneric>
class Vector3
{
template <typename OtherTag>
explicit Vector3(const Vector3<OtherTag>& rhs) { /* ... */ }
// template <typename OtherTag>
// operator Vector3<OtherTag>() const { return /* ... */ }
};
Если вы хотите жить опасно, вы можете опустить ключевое слово explicit
или включите оператор неявного преобразования.Это даст «преимущество» в том, что вы сможете включить разнородные разрешения операторов, например, так:
Position pos;
Direction dir;
Generic gen;
dir = gen + pos; // you see why I call it 'promiscuous'?
Я бы порекомендовал (вместо) определить явные операторыдля подобных случаев (free functions:)
Position operator+(const Position& v, const Translation& d) { /* .... */ }
Таким образом, ваша модель класса отражает семантику ваших классов.
C ++ 0x, возможно, будет содержать вещи для включения явногооператоры преобразования , IIRC:
В случае преобразования конструкторов вы можете отключить неявное преобразование, объявив конструктор явным. Предложение N1592 расширяет семантику этого ключевого слова.для всех операторов преобразования.Оператор преобразования, объявленный явным, не будет выполнять неявное преобразование.Вместо этого программист должен будет вызвать его явно