tmruss
tmruss

Reputation: 322

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);
}

Upvotes: 1

Views: 66

Answers (1)

John Zwinck
John Zwinck

Reputation: 249394

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);
}

Upvotes: 4

Related Questions