If we have a set of class
es or struct
s such as:
struct Point
{
float x;
float y;
};
struct Square
{
Point topLeft;
float width;
};
struct Circle
{
float radius;
Point middle;
};
If we need to add some functionality to to these, does something like below make sense?
inline Point middleOf(const Square &square)
{
float halfWidth(square.width/2.0f);
return Point{
square.topLeft.x + halfWidth,
square.topLeft.y + halfWidth};
}
inline Point middleOf(const Circle &circle)
{
return circle.middle;
}
class MoveSquare
{
public:
MoveSquare(Square &squareToMove)
:
squareToMove(squareToMove)
{}
void to(const Point &target)
{
squareToMove.topLeft = offsetHalfWidth(target);
}
private:
Point offsetHalfWidth(Point p)
{
const float halfWidth(squareToMove.width / 2.0f);
return Point{
p.x - halfWidth,
p.y - halfWidth};
}
private:
Square &squareToMove;
};
class MoveCircle
{
public:
MoveCircle(Circle &circle)
:
circleToMove(circle)
{}
void to(Point position)
{
circleToMove.middle = position;
}
private:
Circle &circleToMove;
};
inline MoveSquare move(Square &square)
{
return MoveSquare{square};
}
inline MoveCircle move(Circle &circle)
{
return MoveCircle{circle};
}
The main idea is being able to have code that reads like a sentence. Such as:
int main() {
Square aSquare;
aSquare.topLeft = Point{1,1};
aSquare.width = 3;
Circle aCircle;
aCircle.middle = Point{1,1};
aCircle.radius = 2;
move(aSquare).to(Point{1,1});
move(aSquare).to(middleOf(aCircle));
move(aCircle).to(middleOf(aSquare));
return 0;
}
move
, should have global visibility, if you want to use it for readability. Otherwise you have touse namespace
it. I don't think this is a good idea. Do you thought about koenig lookup, for this? \$\endgroup\$aSquare.moveTo(Point{1,1});
oraSquare.moveTo(aCircle.center())
\$\endgroup\$