Compare commits
5 commits
1f69ccd417
...
a07f005e09
Author | SHA1 | Date | |
---|---|---|---|
Bruno BELANYI | a07f005e09 | ||
Bruno BELANYI | 2b02f67da6 | ||
Bruno BELANYI | 788986fd29 | ||
Bruno BELANYI | fddee859f9 | ||
Bruno BELANYI | fe41593490 |
|
@ -60,20 +60,18 @@ Here is an example:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
struct SpaceObject {
|
struct SpaceObject {
|
||||||
virtual ~SpaceObject() = default;
|
|
||||||
|
|
||||||
// Pure virtual method, which must be overridden by non-abstract sub-classes
|
// Pure virtual method, which must be overridden by non-abstract sub-classes
|
||||||
virtual void impact() = 0;
|
virtual void impact() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Asteroid : SpaceObject {
|
struct Asteroid {
|
||||||
// Override the method for asteroid impacts
|
// Override the method for asteroid impacts
|
||||||
void impact() override {
|
void impact() override {
|
||||||
std::cout << "Bang!\n";
|
std::cout << "Bang!\n";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Spaceship : SpaceObject {
|
struct Spaceship {
|
||||||
// Override the method for spaceship impacts
|
// Override the method for spaceship impacts
|
||||||
void impact() override {
|
void impact() override {
|
||||||
std::cout << "Crash!\n";
|
std::cout << "Crash!\n";
|
||||||
|
@ -281,8 +279,8 @@ This is the downside I was pointing out in our previous sections:
|
||||||
method to the `SpaceObject` interface to implement a new operation.
|
method to the `SpaceObject` interface to implement a new operation.
|
||||||
* Operation extension: one can easily create a new function when using the
|
* Operation extension: one can easily create a new function when using the
|
||||||
`std::variant` based representation, as pattern-matching easily allows us to
|
`std::variant` based representation, as pattern-matching easily allows us to
|
||||||
only handle the kinds of values we are interested in. But adding a new
|
only handle the kinds of values we are interested in. But adding new
|
||||||
`SpaceObject` variant means we need to modify and re-compile every
|
`SpaceObject` variant means we need to modify and/or re-compile every
|
||||||
`std::visit` call to handle the new variant.
|
`std::visit` call to handle the new variant.
|
||||||
|
|
||||||
There is currently no (good) way in standard C++ to tackle the Expression
|
There is currently no (good) way in standard C++ to tackle the Expression
|
||||||
|
@ -296,40 +294,3 @@ In the meantime, one can find some libraries (like [`yomm2`][yomm2]) that
|
||||||
reduce the amount of boiler-plate needed to emulate this feature.
|
reduce the amount of boiler-plate needed to emulate this feature.
|
||||||
|
|
||||||
[yomm2]: https://github.com/jll63/yomm2
|
[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
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
Loading…
Reference in a new issue