Compare commits

..

6 commits

View file

@ -60,18 +60,20 @@ Here is an example:
```cpp
struct SpaceObject {
virtual ~SpaceObject() = default;
// Pure virtual method, which must be overridden by non-abstract sub-classes
virtual void impact() = 0;
};
struct Asteroid {
struct Asteroid : SpaceObject {
// Override the method for asteroid impacts
void impact() override {
std::cout << "Bang!\n";
}
};
struct Spaceship {
struct Spaceship : SpaceObject {
// Override the method for spaceship impacts
void impact() override {
std::cout << "Crash!\n";
@ -279,8 +281,8 @@ This is the downside I was pointing out in our previous sections:
method to the `SpaceObject` interface to implement a new operation.
* Operation extension: one can easily create a new function when using the
`std::variant` based representation, as pattern-matching easily allows us to
only handle the kinds of values we are interested in. But adding new
`SpaceObject` variant means we need to modify and/or re-compile every
only handle the kinds of values we are interested in. But adding a new
`SpaceObject` variant means we need to modify and re-compile every
`std::visit` call to handle the new variant.
There is currently no (good) way in standard C++ to tackle the Expression
@ -294,3 +296,40 @@ In the meantime, one can find some libraries (like [`yomm2`][yomm2]) that
reduce the amount of boiler-plate needed to emulate this feature.
[yomm2]: https://github.com/jll63/yomm2
```cpp
#include <yorel/yomm2/keywords.hpp>
struct SpaceObject {
virtual ~SpaceObject() = default;
};
struct Asteroid : SpaceObject { /* fields, methods, etc... */ };
struct Spaceship : SpaceObject { /* fields, methods, etc... */ };
// Register all sub-classes of `SpaceObject` for use with open methods
register_classes(SpaceObject, Asteroid, Spaceship);
// Register the `collide` open method, which dispatches on two arguments
declare_method(void, collide, (virtual_<SpaceObject&>, virtual_<SpaceObject&>));
// Write the different implementations of `collide`
define_method(void, collide, (Asteroid& left, Asteroid& right)) { /* work */ }
define_method(void, collide, (Asteroid& left, Spaceship& right)) { /* work */ }
define_method(void, collide, (Spaceship& left, Asteroid& right)) { /* work */ }
define_method(void, collide, (Spaceship& left, Spaceship& right)) { /* work */ }
int main() {
yorel::yomm2::update_methods();
auto asteroid = std::make_unique<Asteroid>();
auto spaceship = std::make_unique<Spaceship>();
collide(*asteroid, *spaceship); // Calls (Asteroid, Spaceship) version
collide(*spaceship, *asteroid); // Calls (Spaceship, Asteroid) version
collide(*asteroid, *asteroid); // Calls (Asteroid, Asteroid) version
collide(*spaceship, *spaceship); // Calls (Spaceship, Spaceship) version
}
```