Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type-separate relative and absolute coords #4401

Open
madmaxoft opened this issue Sep 28, 2019 · 3 comments

Comments

@madmaxoft
Copy link
Member

@madmaxoft madmaxoft commented Sep 28, 2019

When working with block coords, we sometimes use relative coords and sometimes absolute coords. It'd be great if the two were unable to mix. Right now the "best practice" is to represent both as Vector3i, which is prone to errors when changing the code - was the vector abs or rel? Is the input to the function abs or rel? If there was a way to make the coords still use the Vector3i semantics, but disallow assignment from relative to absolute and vice versa, that could prevent nasty bugs. Perhaps tagging a Vector3i descendant?

@madmaxoft

This comment has been minimized.

Copy link
Member Author

@madmaxoft madmaxoft commented Sep 29, 2019

@peterbell10 could you think of some magic to do this? :)

@peterbell10

This comment has been minimized.

Copy link
Member

@peterbell10 peterbell10 commented Sep 29, 2019

I guess it depends how fancy you want to get. The simplest solution would be

struct AbsPos: Vector3i
{
  using Vector3i::Vector3i;
};

struct RelPos: Vector3i
{
  using Vector3i::Vector3i;
};

You can convert down the hierarchy but not sideways so

Vector3i v = AbsPos{1, 2, 3};  // works fine
RelPos r = AbsPos{1, 2, 3};    // error: no viable conversion from 'AbsPos' to 'RelPos'
RelPos r; r = AbsPos{1, 2, 3}; // error: no viable overloaded '='

However if you try and do any arithmetic with them it will just return Vector3i.

A fancier solution would be to create a TaggedPos class that implements arithmetic like Position + Vector = Position, Position - Position = Vector etc. By templating on a tag type, we can make AbsPos and RelPos share the same implementation but keep them as distinct types. e.g.

template <typename Tag>
struct TaggedPos: Vector3i
{
  using Vector3i::Vector3i;
  TaggedPos operator + (Vector3i v)
  {
    return TaggedPos(Vector3i::operator+(v));
  }
  Vector3i operator - (TaggedPos v) 
  {
    return Vector3i::operator-(v);
  }
  TaggedPos operator - (Vector3i v)
  {
    return TaggedPos(Vector3i::operator-(v));
  }
  // etc ...
};

struct AbsolutePositionTag;
using AbsPos = TaggedPos<AbsolutePositionTag>;

struct RelativePositionTag;
using RelPos = TaggedPos<RelativePositionTag>;
@madmaxoft

This comment has been minimized.

Copy link
Member Author

@madmaxoft madmaxoft commented Oct 1, 2019

The "fancier" solution looks really nice. Unless there's some problem with Lua API, I'd go that way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.