tmruss tmruss - 1 month ago 14
C++ Question

Strongly typed solution for "types" of Points

I am trying to represent points in two "types of space": Window space and world space. I have a 2d vector class which is the raw data.

What is the best way to "strongly type" these two without re-writing my 2d vector class? Ie i would have to re-write all the operator+= operator-, operator+ and so forth.

My current code for the two points is below. I'm looking for a "better solution". I define better as strong typing, and able to write code like this:

pos += {0, -1};


Without having to write a full suite of operators for WindowPosition and WorldPosition.

My current solution:

struct WindowPosition
{
template<typename... Args>
WindowPosition(Args&&... args)
: m_coords(std::forward<Args>(args)...)
{}

operator math::v2&() { return m_coords; }
operator const math::v2&() const { return m_coords; };

math::v2 m_coords;
};


struct WorldPosition
{
template<typename... Args>
WorldPosition(Args&&... args)
: m_coords(std::forward<Args>(args)...)
{}

operator math::v2&() { return m_coords; }
operator const math::v2&() const { return m_coords; };

WindowPosition ToWindowPosition()
{
return globals::CAMERA->ToWindowRelative(m_coords);
}

math::v2 m_coords;
};


But this means I have to do this instead: pos.m_coords += {0, -1};

Is there a better way to achieve what I've described above? Or is there a more idiomatic solution?

****EDIT: here is what I ended up going with. Thanks @jzwinck:

struct Window {};
struct World {};

template <typename Tag>
struct Position : math::v2
{
template<typename... Args>
Position(Args&&... args)
: math::v2(std::forward<Args>(args)...)
{}
};

typedef Position<Window> WindowPosition;
typedef Position<World> WorldPosition;

WindowPosition ToWindowPosition(const WorldPosition& pos)
{
return globals::CAMERA->ToWindowRelative(pos);
}

Answer

Templates!

struct Window {};
struct World {};

template <typename Tag>
struct Position
{
  template<typename... Args>
  Position(Args&&... args)
    : m_coords(std::forward<Args>(args)...)
  {}

  operator math::v2&() { return m_coords; }
  operator const math::v2&() const { return m_coords; };

  math::v2 m_coords;
};

typedef Position<Window> WindowPosition;
typedef Position<World> WorldPosition;

WindowPosition ToWindowPosition(const WorldPosition& pos)
{
  return globals::CAMERA->ToWindowRelative(pos);
}