# Migration from Boost.Signals2 This guide helps to migrate large codebase from Boost.Signals2 to `FastSignals` signals/slots library. It helps to solve known migration issues in the right way. During migrations, you will probably face with following things: * You code uses `boost::signals2::` namespace and `` header directly * You code uses third-party headers included implicitly by the `` header ## Reasons migrate from Boost.Signals2 to FastSignals FastSignals API mostly compatible with Boost.Signals2 - there are differences, and all differences has their reasons explained below. Comparing to Boost.Signals2, FastSignals has following pros: * FastSignals is not header-only - so binary code will be more compact * FastSignals implemented using C++17 with variadic templates, `constexpr if` and other modern metaprogramming techniques - so it compiles faster and, again, binary code will be more compact * FastSignals probably will faster than Boost.Signals2 for your codebase because with FastSignals you don't pay for things that you don't use, with one exception: you always pay for the multithreading support ## Step 1: Create header with aliases ## Step 2: Rebuild and fix compile errors ### 2.1 Add missing includes Boost.Signals2 is header-only library. It includes a lot of STL/Boost stuff while FastSignals does not: ```cpp #include // Also includes std::map, boost::variant, boost::optional, etc. // Compiled OK even without `#include `! std::map CreateMyMap(); ``` With FastSignals, you must include headers like `` manually. The following table shows which files should be included explicitly if you see compile erros after migration. | Class | Header | |--------------------|:--------------------------------------:| | std::map | `#include ` | | boost::variant | `#include ` | | boost::optional | `#include ` | | boost::scoped_ptr | `#include ` | | boost::noncopyable | `#include ` | | boost::bind | `#include ` | | boost::function | `#include ` | If you just want to compile you code, you can add following includes in you `signals.h` header: ```cpp // WARNING: [libfastsignals] we do not recommend to include following extra headers. #include #include #include #include #include #include #include ``` ### 2.2 Remove redundant returns for void signals With Boost.Signals2, following code compiled without any warning: ```cpp boost::signals2::signal event; event.connect([] { return true; }); ``` With FastSignals, slot cannot return non-void value when for `signal`. You must fix your code: just remove returns from your slots or add lambdas to wrap slot and ignore it result. ### 2.3 Replace track() and track_foreign() with bind_weak_ptr() Boost.Signals2 [can track connected objects lifetype](https://www.boost.org/doc/libs/1_55_0/doc/html/signals2/tutorial.html#idp204830936) using `track(...)` and `track_foreign(...)` methods. In the following example `Entity` created with `make_shared`, and `Entity::get_print_slot()` creates slot function which tracks weak pointer to Entity: ```cpp #include #include #include using VoidSignal = boost::signals2::signal; using VoidSlot = VoidSignal::slot_type; struct Entity : std::enable_shared_from_this { int value = 42; VoidSlot get_print_slot() { // Here track() tracks object itself. return VoidSlot(std::bind(&Entity::print, this)).track_foreign(shared_from_this()); } void print() { std::cout << "print called, num = " << value << std::endl; } }; int main() { VoidSignal event; auto entity = std::make_shared(); event.connect(entity->get_print_slot()); // Here slot called - it prints `print called, num = 42` event(); entity = nullptr; // This call does nothing. event(); } ``` FastSignals uses another approach: `bind_weak` function: ```cpp #include #include using VoidSignal = fastsignals::signal; using VoidSlot = VoidSignal::slot_type; struct Entity : std::enable_shared_from_this { int value = 42; VoidSlot get_print_slot() { // Here fastsignals::bind_weak() used instead of std::bind. return fastsignals::bind_weak(&Entity::print, weak_from_this()); } void print() { std::cout << "print called, num = " << value << std::endl; } }; int main() { VoidSignal event; auto entity = std::make_shared(); event.connect(entity->get_print_slot()); // Here slot called - it prints `slot called, num = 42` event(); entity = nullptr; // Here nothing happens - no exception, no slot call. event(); } ``` ### FastSignals Differences in Result Combiners ## Step 3: Run Tests Run all automated tests that you have (unit tests, integration tests, system tests, stress tests, benchmarks, UI tests). Probably you will see no errors. If you see any, please report an issue.