Reactive Programming in C++: RxCpp and Boost.Signals2 Libraries

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Reactive Programming in C++: Overview of RxCpp and Boost.Signals2 Libraries



Reactive Programming is a paradigm focused on asynchronous data streams and the propagation of changes. In C++, this paradigm is implemented through libraries that allow handling events, signals, and asynchronous data sequences in a declarative way. In this article, we will look at two key libraries for reactive programming in C++: RxCpp (Reactive Extensions for C++) and Boost.Signals2. Both libraries solve the problem of event handling, but with different levels of complexity and functionality.



Why is reactive programming needed in C++?



Traditional imperative code often becomes complex when dealing with asynchronous events, user input, network requests, or multithreading. Reactive programming offers:



  • Declarative approach: You describe "what" should happen, not "how".
  • Stream composition: Easily combine, filter, and transform data streams.
  • Multithreading management: Built-in mechanisms for context switching and synchronization.
  • Error handling: A unified pipeline for data and exceptions.


The RxCpp Library



RxCpp is a port of Reactive Extensions (Rx) for C++. It provides a powerful set of operators for working with asynchronous data sequences. The main concepts are: observable (data source) and observer (subscriber).



Installation

RxCpp is a header-only library. Simply clone the repository and include the header files:

#include <rxcpp/rx.hpp>using namespace rxcpp;using namespace rxcpp::sources;using namespace rxcpp::operators;


Example 1: Simple subscription to a number stream

Let's create an observable that generates numbers from 1 to 5, and subscribe to it:

#include <iostream>#include <rxcpp/rx.hpp>

int main() { auto values = range(1, 5); // observable: 1,2,3,4,5

values. subscribe([](int v) { std::cout << "Received: " << v << std::endl; }, []() { std::cout << "Stream completed" << std::endl; });

return 0;}


Example 2: Filtering and transformation

Reactive operators allow you to easily manipulate data. Let's filter even numbers and multiply them by 10:

auto values = range(1, 10);

values .filter([](int v) { return v % 2 == 0; }) // only even .map([](int v) { return v * 10; }) // multiply by 10 .subscribe([](int v) { std::cout << "Result: " << v << std::endl; });// Output: 20, 40, 60, 80, 100


Example 3: Merging streams

Let's merge two streams using the merge operator:

auto stream1 = interval(std::chrono::milliseconds(100)).take(3);auto stream2 = interval(std::chrono::milliseconds(150)).take(3);

stream1.merge(stream2) .subscribe([](long v) { std::cout << v << " "; });// Possible output: 0 0 1 2 1 2 (order may vary)


The Boost.Signals2 Library



Boost.Signals2 is a library for implementing signals and slots. It is part of the Boost libraries and provides a type-safe mechanism for callbacks. Unlike RxCpp, Signals2 is not designed for working with data streams, but rather for handling discrete events.



Main Concepts

  • Signal: an object that can be "invoked" and will notify all its subscribers.
  • Slot: a function or functional object that is connected to a signal.

Recommendations