Random order of arguments in C++ functions

in #cpp8 years ago (edited)

Some time ago, while I was working on 3D game engine (which is still unfinished btw.) I encountered simple but quite interesting design problem to solve. Let's prototype simple collision system with two shapes available:

class Box {
 // ...
};

class Sphere {
 // ...
};

Now let's consider a method that will test if two shapes collide with each other:

class Sphere;

class Box {
 // ...
public:
 bool collides(const Box&) const;
 bool collides(const Sphere&) const;
};

class Sphere {
 // ...
public:
 bool collides(const Box&) const;
 bool collides(const Sphere&) const;
};

After implementing collides methods we can see that bool Box::collides(const Sphere&) const and bool Sphere:collides(const Box&) const are almost the same - they do the same job and the only difference is in argument type and this pointer type. Logically, box colliding with sphere is the same as sphere colliding with box. Clearly we need to change design here. Function will be much better here than method:

class Box {
 // ...
};

class Sphere {
 // ...
};

bool collide(const Box&, const Box&);
bool collide(const Box&, const Sphere&);
bool collide(const Sphere&, const Sphere&);

Now collision between box and sphere can be implemented only once. So let's try it:

if (collide(sphere, box)) {
 // ...
}

Well, the code didn't compile! The problem is that bool collide(const Sphere&, const Box&) doesn't exist. We have bool collide(const Box&, const Sphere&) which will fit here, but it make sense here to have both versions of the function available to use. In order to achieve that we can extract collision checker code to internal function and use it in both cases:

bool collideImpl(const Box& box, const Sphere& box);

bool collide(const Sphere& sphere, const Box& box)
{
 collideImpl(box, sphere);
}
bool collide(const Box& box, const Sphere& box)
{
 collideImpl(box, sphere);
}

It's better now but still too much of typing. C++ has pretty good type system which is Turing complete. Let's try to use is to do the job. Remember the problem when bool collide(const Sphere&, const Box&) wasn't available and lack of it caused compilation error? What if we try to use bool collide(const Sphere&, const Box&) when bool collide(const Sphere&, const Box&) is not available? Thanks to template instantiation it is really easy. All we have to do is to add template that will be used when concrete function is not provided. This is the final version of the code:

class Box {
 // ...
};

class Sphere {
// ...
};

bool collide(const Box&, const Box&);
bool collide(const Box&, const Sphere&);
bool collide(const Sphere&, const Sphere&);

template<typename A, typename B>
bool collide(const A& a, const B& b)
{
 collide(b, a);
}

Here is how it can be used:

Box box{...};
Sphere sph{...};

if (collide(box, sph) == collide(sph, box))
 std::cout << "It works!\n";

Sort:  

Congratulations @grabarz! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!

Congratulations @grabarz! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes received

Click on any badge to view your own Board of Honnor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!

Congratulations @grabarz! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of comments received
Award for the number of upvotes received
You published your First Post

Click on any badge to view your own Board of Honnor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!

Congratulations @grabarz! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

You got your First payout

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!