-
Dominik Charousset authored
The composable behavior was intended to make actor states re-usable. However, they turned out to not deliver on that promise. One major flaw in this approach comes from the way inheritance works in C++. In a scenario with multiple base types providing the same virtual function, overrides in one base type may not override all functions for that signature. Consider the following example: ```c++ struct foo { virtual void hello() = 0; }; struct bar { virtual void hello() = 0; }; struct a : foo { void hello() override { // nop } }; struct b : bar, a { }; int main(int, char **) { b obj; // ... oops: compiler error! } ``` This rarely becomes an issue in most C++ code. However, it's very easy to run into this compiler error using the composable behaviors by implementing overlapping typed actor handles. Aside from this subtle issue, compiler errors produced by the composable actor API turned out to be very hard to parse. Getting a handler signature wrong or missing an override quickly turns into guess games. Last but not least, the `caf::param` API became a necessary evil to support actors that may or may not require mutable access to a tuple. But it adds another layer of complexity as well as runtime overhead. The idea of implementing actors with re-usable pieces is still worth pursuing, but this experiment did not pay out.
4406ed26