SlideShare a Scribd company logo
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 1/108
Mateusz Pusz
April 12, 2019
E ective replacement of dynamic
polymorphism with
std::variant
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 2/108
Why?
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 3/108
• Time required to perform some action or to produce some result
• Measured in units of time like hours, minutes, seconds, nanoseconds or clock periods
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Why?
LATENCY
3
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 4/108
• Time required to perform some action or to produce some result
• Measured in units of time like hours, minutes, seconds, nanoseconds or clock periods
• In capital markets, the use of algorithmic trading to react to market events faster than the competition
to increase profitability of trades
• Many use cases where predictability of latency in message delivery is just as important, if not more
important than achieving a low average latency
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Why?
LATENCY
LOW LATENCY
3
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 5/108
• In Low Latency system we care a lot about
WCET (Worst Case Execution Time)
• In order to limit WCET we should limit the
usage of specific C++ language features
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
How NOT to develop software that have predictable
performance?
4
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 6/108
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Things to avoid on the fast path
5
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 7/108
• C++ tools that trade performance for usability (e.g. std::shared_ptr, std::function)
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Things to avoid on the fast path
5
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 8/108
• C++ tools that trade performance for usability (e.g. std::shared_ptr, std::function)
• Throwing exceptions on a likely code path
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Things to avoid on the fast path
5
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 9/108
• C++ tools that trade performance for usability (e.g. std::shared_ptr, std::function)
• Throwing exceptions on a likely code path
• Dynamic polymorphism
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Things to avoid on the fast path
5
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 10/108
• C++ tools that trade performance for usability (e.g. std::shared_ptr, std::function)
• Throwing exceptions on a likely code path
• Dynamic polymorphism
• Multiple inheritance
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Things to avoid on the fast path
5
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 11/108
• C++ tools that trade performance for usability (e.g. std::shared_ptr, std::function)
• Throwing exceptions on a likely code path
• Dynamic polymorphism
• Multiple inheritance
• RTTI
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Things to avoid on the fast path
5
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 12/108
• C++ tools that trade performance for usability (e.g. std::shared_ptr, std::function)
• Throwing exceptions on a likely code path
• Dynamic polymorphism
• Multiple inheritance
• RTTI
• Dynamic memory allocations
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Things to avoid on the fast path
5
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 13/108
• Dynamic polymorphism
• Dynamic memory allocations
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Things to avoid on the fast path
• C++ tools that trade performance for usability (e.g. std::shared_ptr, std::function)
• Throwing exceptions on a likely code path
• Multiple inheritance
• RTTI
6
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 14/108
How?
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 15/108
class base : noncopyable {
public:
virtual ~base() = default;
virtual void foo() = 0;
};
class x : public base {
public:
void foo() override;
};
class y : public base {
public:
void foo() override;
};
std::unique_ptr<base> b = std::make_unique<x>();
b->foo();
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
How?
DYNAMIC POLYMORPHISM
8
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 16/108
class base : noncopyable {
public:
virtual ~base() = default;
virtual void foo() = 0;
};
class x : public base {
public:
void foo() override;
};
class y : public base {
public:
void foo() override;
};
std::unique_ptr<base> b = std::make_unique<x>();
b->foo();
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
How?
DYNAMIC POLYMORPHISM
8
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 17/108
class base : noncopyable {
public:
virtual ~base() = default;
virtual void foo() = 0;
};
class x : public base {
public:
void foo() override;
};
class y : public base {
public:
void foo() override;
};
std::unique_ptr<base> b = std::make_unique<x>();
b->foo();
struct x { void foo(); };
struct y { void foo(); };
std::variant<x, y> b;
std::visit([](auto&& v){ v.foo(); }, b);
• Shorter
• Faster
• Value semantics
• Works on unrelated classes
• More flexible thanks to duck typing
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
How?
DYNAMIC POLYMORPHISM VARIANT
8
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 18/108
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
THE END
T H A N K Y O U !
9
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 19/108
Bonus slides
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 20/108
Abstract machine that can be in exactly one of a finite number of
states at any given time.
-- Wikipedia
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Finite State Machine
11
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 21/108
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Finite State Machine
12
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 22/108
• State changes to another in a response to
some external inputs called events
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Finite State Machine
12
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 23/108
• State changes to another in a response to
some external inputs called events
• The change from one state to another is
called a transition
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Finite State Machine
12
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 24/108
• State changes to another in a response to
some external inputs called events
• The change from one state to another is
called a transition
• A FSM is defined by
– a list of states
– its initial state
– the conditions for each transition
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Finite State Machine
12
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 25/108
Single dynamic dispatch
CASE #1
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 26/108
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Class diagram
14
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 27/108
template<typename Event>
class state : noncopyable {
public:
virtual ~state() = default;
virtual std::unique_ptr<state> on_event(Event) = 0;
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Single dynamic dispatch
15
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 28/108
template<typename Event>
class state : noncopyable {
public:
virtual ~state() = default;
virtual std::unique_ptr<state> on_event(Event) = 0;
};
template<typename Event>
class fsm {
std::unique_ptr<state<Event>> state_;
public:
explicit fsm(std::unique_ptr<state<Event>> state) : state_(std::move(state)) {}
void dispatch(Event e)
{
auto new_state = state_->on_event(e);
if(new_state)
state_ = std::move(new_state);
}
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Single dynamic dispatch
15
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 29/108
template<typename Event>
class state : noncopyable {
public:
virtual ~state() = default;
virtual std::unique_ptr<state> on_event(Event) = 0;
};
template<typename Event>
class fsm {
std::unique_ptr<state<Event>> state_;
public:
explicit fsm(std::unique_ptr<state<Event>> state) : state_(std::move(state)) {}
void dispatch(Event e)
{
auto new_state = state_->on_event(e);
if(new_state)
state_ = std::move(new_state);
}
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Single dynamic dispatch
16
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 30/108
class connection_fsm : public fsm<event> {
public:
connection_fsm():
fsm<event>(std::make_unique<state_idle>()) {}
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Connection FSM
17
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 31/108
class connection_fsm : public fsm<event> {
public:
connection_fsm():
fsm<event>(std::make_unique<state_idle>()) {}
};
using s = state<event>;
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Connection FSM
17
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 32/108
class connection_fsm : public fsm<event> {
public:
connection_fsm():
fsm<event>(std::make_unique<state_idle>()) {}
};
using s = state<event>;
class state_idle final : public s {
public:
std::unique_ptr<s> on_event(event e) override;
};
class state_connecting final : public s {
static constexpr int n_max = 3;
int n = 0;
public:
std::unique_ptr<s> on_event(event e) override;
};
class state_connected final : public s {
public:
std::unique_ptr<s> on_event(event e) override;
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Connection FSM
17
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 33/108
std::unique_ptr<s> state_idle::on_event(event e)
{
}
std::unique_ptr<s> state_connecting::on_event(event e)
{
}
std::unique_ptr<s> state_connected::on_event(event e)
{
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
18
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 34/108
std::unique_ptr<s> state_idle::on_event(event e)
{
if(e == event::connect)
return std::make_unique<state_connecting>();
return nullptr;
}
std::unique_ptr<s> state_connecting::on_event(event e)
{
}
std::unique_ptr<s> state_connected::on_event(event e)
{
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
18
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 35/108
std::unique_ptr<s> state_idle::on_event(event e)
{
if(e == event::connect)
return std::make_unique<state_connecting>();
return nullptr;
}
std::unique_ptr<s> state_connecting::on_event(event e)
{
switch(e) {
case event::connected:
return std::make_unique<state_connected>();
case event::timeout:
return ++n < n_max ?
nullptr : std::make_unique<state_idle>();
default:
return nullptr;
}
}
std::unique_ptr<s> state_connected::on_event(event e)
{
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
18
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 36/108
std::unique_ptr<s> state_idle::on_event(event e)
{
if(e == event::connect)
return std::make_unique<state_connecting>();
return nullptr;
}
std::unique_ptr<s> state_connecting::on_event(event e)
{
switch(e) {
case event::connected:
return std::make_unique<state_connected>();
case event::timeout:
return ++n < n_max ?
nullptr : std::make_unique<state_idle>();
default:
return nullptr;
}
}
std::unique_ptr<s> state_connected::on_event(event e)
{
if(e == event::disconnect)
return std::make_unique<state_idle>();
return nullptr;
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
18
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 37/108
std::unique_ptr<s> state_idle::on_event(event e)
{
if(e == event::connect)
return std::make_unique<state_connecting>();
return nullptr;
}
std::unique_ptr<s> state_connecting::on_event(event e)
{
switch(e) {
case event::connected:
return std::make_unique<state_connected>();
case event::timeout:
return ++n < n_max ?
nullptr : std::make_unique<state_idle>();
default:
return nullptr;
}
}
std::unique_ptr<s> state_connected::on_event(event e)
{
if(e == event::disconnect)
return std::make_unique<state_idle>();
return nullptr;
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
The slow part
19
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 38/108
• Fold expressions come handy ;-)
template<typename Fsm, typename... Events>
void dispatch(Fsm& fsm, Events... events)
{
(fsm.dispatch(events), ...);
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Testing transitions
20
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 39/108
• Fold expressions come handy ;-)
template<typename Fsm, typename... Events>
void dispatch(Fsm& fsm, Events... events)
{
(fsm.dispatch(events), ...);
}
• Simple message flow
connection_fsm fsm;
dispatch(fsm, event::connect, event::timeout, event::connected, event::disconnect);
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Testing transitions
20
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 40/108
• Open to new alternatives
– new derived types may be added by clients at any point of time (long a er base class
implementation is finished)
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Single dynamic dispatch
21
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 41/108
• Open to new alternatives
– new derived types may be added by clients at any point of time (long a er base class
implementation is finished)
• Closed to new operations
– clients cannot add new operations to dynamic dispatch
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Single dynamic dispatch
21
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 42/108
• Open to new alternatives
– new derived types may be added by clients at any point of time (long a er base class
implementation is finished)
• Closed to new operations
– clients cannot add new operations to dynamic dispatch
• Multi-level
– many levels of inheritance possible
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Single dynamic dispatch
21
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 43/108
• Open to new alternatives
– new derived types may be added by clients at any point of time (long a er base class
implementation is finished)
• Closed to new operations
– clients cannot add new operations to dynamic dispatch
• Multi-level
– many levels of inheritance possible
• Object Oriented
– whole framework is based on objects
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Single dynamic dispatch
21
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 44/108
Double dynamic dispatch
CASE #2
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 45/108
class event : noncopyable {
public:
virtual ~event() = default;
};
class event_connect final : public event {
std::string_view address_;
public:
explicit event_connect(std::string_view address): address_(address) {}
std::string_view address() const { return address_; }
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
What if we want our events to pass data?
23
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 46/108
class event : noncopyable {
public:
virtual ~event() = default;
};
class event_connect final : public event {
std::string_view address_;
public:
explicit event_connect(std::string_view address): address_(address) {}
std::string_view address() const { return address_; }
};
std::unique_ptr<state> state_idle::on_event(const event& e)
{
if(auto ptr = dynamic_cast<const event_connect*>(&e)) { /* ... */ }
else { /* ... */ }
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
What if we want our events to pass data?
23
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 47/108
class event : noncopyable {
public:
virtual ~event() = default;
};
class event_connect final : public event {
std::string_view address_;
public:
explicit event_connect(std::string_view address): address_(address) {}
std::string_view address() const { return address_; }
};
std::unique_ptr<state> state_idle::on_event(const event& e)
{
if(auto ptr = dynamic_cast<const event_connect*>(&e)) { /* ... */ }
else { /* ... */ }
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
What if we want our events to pass data?
A really bad idea :-(
23
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 48/108
Special form of multiple dispatch, and a mechanism that
dispatches a function call to di erent concrete functions
depending on the runtime types of two objects involved in the call
-- Wikipedia
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Double dispatch (aka Visitor Pattern)
24
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 49/108
template<typename State>
struct event : private noncopyable {
virtual ~event() = default;
virtual std::unique_ptr<State> dispatch(State& s) const = 0;
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Double dispatch (aka Visitor Pattern)
25
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 50/108
template<typename State>
struct event : private noncopyable {
virtual ~event() = default;
virtual std::unique_ptr<State> dispatch(State& s) const = 0;
};
template<typename State, typename Event>
class fsm {
std::unique_ptr<State> state_;
public:
explicit fsm(std::unique_ptr<State> state) : state_(std::move(state)) {}
void dispatch(const Event& e)
{
auto new_state = e.dispatch(*state_);
if(new_state)
state_ = std::move(new_state);
}
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Double dispatch (aka Visitor Pattern)
25
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 51/108
template<typename State>
struct event : private noncopyable {
virtual ~event() = default;
virtual std::unique_ptr<State> dispatch(State& s) const = 0;
};
struct event_connect final : public event<state> {
std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); }
// ...
};
struct event_connected final : public event<state> {
std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); }
};
struct event_disconnect final : public event<state> {
std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); }
};
struct event_timeout final : public event<state> {
std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); }
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Double dispatch (aka Visitor Pattern)
26
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 52/108
template<typename State>
struct event : private noncopyable {
virtual ~event() = default;
virtual std::unique_ptr<State> dispatch(State& s) const = 0;
};
class state : noncopyable {
public:
virtual ~state() = default;
virtual std::unique_ptr<state> on_event(const event_connect&) { return nullptr; }
virtual std::unique_ptr<state> on_event(const event_connected&) { return nullptr; }
virtual std::unique_ptr<state> on_event(const event_disconnect&) { return nullptr; }
virtual std::unique_ptr<state> on_event(const event_timeout&) { return nullptr; }
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Double dispatch (aka Visitor Pattern)
27
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 53/108
template<typename State>
struct event : private noncopyable {
virtual ~event() = default;
virtual std::unique_ptr<State> dispatch(State& s) const = 0;
};
class state : noncopyable {
public:
virtual ~state() = default;
virtual std::unique_ptr<state> on_event(const event_connect&) { return nullptr; }
virtual std::unique_ptr<state> on_event(const event_connected&) { return nullptr; }
virtual std::unique_ptr<state> on_event(const event_disconnect&) { return nullptr; }
virtual std::unique_ptr<state> on_event(const event_timeout&) { return nullptr; }
};
class state_idle final : public state {
public:
using state::on_event;
std::unique_ptr<state> on_event(const event_connect& e) override
{
return std::make_unique<state_connecting>(std::string(e.address()));
}
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Double dispatch (aka Visitor Pattern)
27
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 54/108
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Class diagram
28
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 55/108
template<typename State>
struct event : private noncopyable {
virtual ~event() = default;
virtual std::unique_ptr<State> dispatch(State& s) const = 0;
};
struct event_connect final : public event<state> {
std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); }
// ...
};
struct event_connected final : public event<state> {
std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); }
};
struct event_disconnect final : public event<state> {
std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); }
};
struct event_timeout final : public event<state> {
std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); }
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Curiously Recurring Template Pattern (CRTP)
29
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 56/108
template<typename State>
struct event : private noncopyable {
virtual ~event() = default;
virtual std::unique_ptr<State> dispatch(State& s) const = 0;
};
template<typename Child>
struct event_crtp : event<state> {
std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*static_cast<const Child*>(this)); }
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Curiously Recurring Template Pattern (CRTP)
30
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 57/108
template<typename State>
struct event : private noncopyable {
virtual ~event() = default;
virtual std::unique_ptr<State> dispatch(State& s) const = 0;
};
template<typename Child>
struct event_crtp : event<state> {
std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*static_cast<const Child*>(this)); }
};
struct event_connect final : public event_crtp<event_connect> {
// ...
};
struct event_connected final : public event_crtp<event_connected> {};
struct event_disconnect final : public event_crtp<event_disconnect> {};
struct event_timeout final : public event_crtp<event_timeout> {};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Curiously Recurring Template Pattern (CRTP)
30
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 58/108
template<typename State>
struct event : private noncopyable {
virtual ~event() = default;
virtual std::unique_ptr<State> dispatch(State& s) const = 0;
};
template<typename Child>
struct event_crtp : event<state> {
std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*static_cast<const Child*>(this)); }
};
struct event_connect final : public event_crtp<event_connect> {
explicit event_connect(std::string_view address): address_(address) {}
std::string_view address() const { return address_; }
private:
std::string_view address_;
};
struct event_connected final : public event_crtp<event_connected> {};
struct event_disconnect final : public event_crtp<event_disconnect> {};
struct event_timeout final : public event_crtp<event_timeout> {};
• Hey look ma, now all fits on one slide ;-)
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Curiously Recurring Template Pattern (CRTP)
31
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 59/108
std::unique_ptr<state>
state_idle::on_event(const event_connect& e)
{
}
std::unique_ptr<state>
state_connecting::on_event(const event_connected&)
{
}
std::unique_ptr<state>
state_connecting::on_event(const event_timeout&)
{
}
std::unique_ptr<state>
state_connected::on_event(const event_disconnect&)
{
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
32
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 60/108
std::unique_ptr<state>
state_idle::on_event(const event_connect& e)
{
return std::make_unique<state_connecting>(
std::string{e.address()});
}
std::unique_ptr<state>
state_connecting::on_event(const event_connected&)
{
}
std::unique_ptr<state>
state_connecting::on_event(const event_timeout&)
{
}
std::unique_ptr<state>
state_connected::on_event(const event_disconnect&)
{
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
32
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 61/108
std::unique_ptr<state>
state_idle::on_event(const event_connect& e)
{
return std::make_unique<state_connecting>(
std::string{e.address()});
}
std::unique_ptr<state>
state_connecting::on_event(const event_connected&)
{
return std::make_unique<state_connected>();
}
std::unique_ptr<state>
state_connecting::on_event(const event_timeout&)
{
}
std::unique_ptr<state>
state_connected::on_event(const event_disconnect&)
{
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
32
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 62/108
std::unique_ptr<state>
state_idle::on_event(const event_connect& e)
{
return std::make_unique<state_connecting>(
std::string{e.address()});
}
std::unique_ptr<state>
state_connecting::on_event(const event_connected&)
{
return std::make_unique<state_connected>();
}
std::unique_ptr<state>
state_connecting::on_event(const event_timeout&)
{
return ++n < n_max ?
nullptr : std::make_unique<state_idle>();
}
std::unique_ptr<state>
state_connected::on_event(const event_disconnect&)
{
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
32
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 63/108
std::unique_ptr<state>
state_idle::on_event(const event_connect& e)
{
return std::make_unique<state_connecting>(
std::string{e.address()});
}
std::unique_ptr<state>
state_connecting::on_event(const event_connected&)
{
return std::make_unique<state_connected>();
}
std::unique_ptr<state>
state_connecting::on_event(const event_timeout&)
{
return ++n < n_max ?
nullptr : std::make_unique<state_idle>();
}
std::unique_ptr<state>
state_connected::on_event(const event_disconnect&)
{
return std::make_unique<state_idle>();
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
32
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 64/108
std::unique_ptr<state>
state_idle::on_event(const event_connect& e)
{
return std::make_unique<state_connecting>(
std::string{e.address()});
}
std::unique_ptr<state>
state_connecting::on_event(const event_connected&)
{
return std::make_unique<state_connected>();
}
std::unique_ptr<state>
state_connecting::on_event(const event_timeout&)
{
return ++n < n_max ?
nullptr : std::make_unique<state_idle>();
}
std::unique_ptr<state>
state_connected::on_event(const event_disconnect&)
{
return std::make_unique<state_idle>();
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
The slow part
33
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 65/108
template<typename Fsm, typename... Events>
void dispatch(Fsm& fsm, const Events&... events)
{
(fsm.dispatch(*events), ...);
}
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Testing transitions
34
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 66/108
template<typename Fsm, typename... Events>
void dispatch(Fsm& fsm, const Events&... events)
{
(fsm.dispatch(*events), ...);
}
dispatch(fsm,
std::make_unique<event_connect>("train-it.eu"),
std::make_unique<event_timeout>(),
std::make_unique<event_connected>(),
std::make_unique<event_disconnect>());
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Testing transitions
34
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 67/108
template<typename Fsm, typename... Events>
void dispatch(Fsm& fsm, const Events&... events)
{
(fsm.dispatch(*events), ...);
}
dispatch(fsm,
std::make_unique<event_connect>("train-it.eu"),
std::make_unique<event_timeout>(),
std::make_unique<event_connected>(),
std::make_unique<event_disconnect>());
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
The slow part
35
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 68/108
• Open to new alternatives
• Closed to new alternatives
– one of class hierarchies fixed at design time and cannot be extended by clients
• Closed to new operations
– clients cannot add new operations to dynamic dispatch
• Multi-level
– many levels of inheritance possible
• Object Oriented
– whole framework is based on objects
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Double dynamic dispatch (aka Visitor Pattern)
36
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 69/108
Variant + external transitions
CASE #3
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 70/108
struct event_connect { std::string_view address; };
struct event_connected {};
struct event_disconnect {};
struct event_timeout {};
using event = std::variant<event_connect, event_connected, event_disconnect, event_timeout>;
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Events and states
EVENTS
38
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 71/108
struct event_connect { std::string_view address; };
struct event_connected {};
struct event_disconnect {};
struct event_timeout {};
using event = std::variant<event_connect, event_connected, event_disconnect, event_timeout>;
struct state_idle {};
struct state_connecting {
static constexpr int n_max = 3;
int n = 0;
std::string address;
};
struct state_connected {};
using state = std::variant<state_idle, state_connecting, state_connected>;
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Events and states
EVENTS
STATES
38
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 72/108
struct transitions {
optional<state> operator()(state_idle&,
const event_connect& e)
{ }
optional<state> operator()(state_connecting&,
const event_connected&)
{ }
optional<state> operator()(state_connecting& s,
const event_timeout&)
{
}
optional<state> operator()(state_connected&,
const event_disconnect&)
{ }
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
39
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 73/108
struct transitions {
optional<state> operator()(state_idle&,
const event_connect& e)
{ return state_connecting{std::string(e.address)}; }
optional<state> operator()(state_connecting&,
const event_connected&)
{ }
optional<state> operator()(state_connecting& s,
const event_timeout&)
{
}
optional<state> operator()(state_connected&,
const event_disconnect&)
{ }
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
39
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 74/108
struct transitions {
optional<state> operator()(state_idle&,
const event_connect& e)
{ return state_connecting{std::string(e.address)}; }
optional<state> operator()(state_connecting&,
const event_connected&)
{ return state_connected{}; }
optional<state> operator()(state_connecting& s,
const event_timeout&)
{
}
optional<state> operator()(state_connected&,
const event_disconnect&)
{ }
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
39
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 75/108
struct transitions {
optional<state> operator()(state_idle&,
const event_connect& e)
{ return state_connecting{std::string(e.address)}; }
optional<state> operator()(state_connecting&,
const event_connected&)
{ return state_connected{}; }
optional<state> operator()(state_connecting& s,
const event_timeout&)
{
return ++s.n < state_connecting::n_max ?
std::nullopt : optional<state>(state_idle{});
}
optional<state> operator()(state_connected&,
const event_disconnect&)
{ }
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
39
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 76/108
struct transitions {
optional<state> operator()(state_idle&,
const event_connect& e)
{ return state_connecting{std::string(e.address)}; }
optional<state> operator()(state_connecting&,
const event_connected&)
{ return state_connected{}; }
optional<state> operator()(state_connecting& s,
const event_timeout&)
{
return ++s.n < state_connecting::n_max ?
std::nullopt : optional<state>(state_idle{});
}
optional<state> operator()(state_connected&,
const event_disconnect&)
{ return state_idle{}; }
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
39
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 77/108
struct transitions {
optional<state> operator()(state_idle&,
const event_connect& e)
{ return state_connecting{std::string(e.address)}; }
optional<state> operator()(state_connecting&,
const event_connected&)
{ return state_connected{}; }
optional<state> operator()(state_connecting& s,
const event_timeout&)
{
return ++s.n < state_connecting::n_max ?
std::nullopt : optional<state>(state_idle{});
}
optional<state> operator()(state_connected&,
const event_disconnect&)
{ return state_idle{}; }
template<typename State, typename Event>
optional<state> operator()(State&,
const Event&) const
{ return std::nullopt; }
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions
39
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 78/108
template<typename StateVariant, typename EventVariant, typename Transitions>
class fsm {
StateVariant state_;
public:
void dispatch(const EventVariant& event)
{
std::optional<StateVariant> new_state = std::visit(Transitions{}, state_, event);
if(new_state)
state_ = *std::move(new_state);
}
};
using connection_fsm = fsm<state, event, transitions>;
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
FSM engine
40
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 79/108
template<typename StateVariant, typename EventVariant, typename Transitions>
class fsm {
StateVariant state_;
public:
void dispatch(const EventVariant& event)
{
std::optional<StateVariant> new_state = std::visit(Transitions{}, state_, event);
if(new_state)
state_ = *std::move(new_state);
}
};
using connection_fsm = fsm<state, event, transitions>;
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
FSM engine
41
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 80/108
template<typename StateVariant, typename EventVariant, typename Transitions>
class fsm {
StateVariant state_;
public:
void dispatch(const EventVariant& event)
{
std::optional<StateVariant> new_state = std::visit(Transitions{}, state_, event);
if(new_state)
state_ = *std::move(new_state);
}
};
using connection_fsm = fsm<state, event, transitions>;
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
FSM engine
42
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 81/108
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Class diagram
43
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 82/108
template<typename Fsm, typename... Events>
void dispatch(Fsm& fsm, Events&&... events)
{
(fsm.dispatch(std::forward<Events>(events)), ...);
}
dispatch(fsm,
event_connect{"train-it.eu"},
event_timeout{},
event_connected{},
event_disconnect{});
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Testing transitions
44
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 83/108
Variant + transitions in FSM
CASE #4
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 84/108
template<typename Derived, typename StateVariant, typename EventVariant>
class fsm {
StateVariant state_;
public:
void dispatch(const EventVariant& event)
{
auto new_state = std::visit(
state_, event);
if(new_state)
state_ = *std::move(new_state);
}
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
FSM engine
46
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 85/108
template<typename Derived, typename StateVariant, typename EventVariant>
class fsm {
StateVariant state_;
public:
void dispatch(const EventVariant& event)
{
Derived& child = static_cast<Derived&>(*this);
auto new_state = std::visit(
[&](auto& s, const auto& e) -> std::optional<StateVariant>
{ return child.on_event(s, e); },
state_, event);
if(new_state)
state_ = *std::move(new_state);
}
};
• CRTP again ;-)
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
FSM engine
46
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 86/108
template<typename Derived, typename StateVariant>
class fsm {
StateVariant state_;
public:
template<typename Event>
void dispatch(Event&& event)
{
Derived& child = static_cast<Derived&>(*this);
auto new_state = std::visit(
[&](auto& s) -> std::optional<StateVariant>
{ return child.on_event(s, std::forward<Event>(event)); },
state_);
if(new_state)
state_ = *std::move(new_state);
}
};
• Visitation on a StateVariant only
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
FSM engine: dispatch() as an overload set
47
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 87/108
class connection_fsm
: public fsm<connection_fsm, state> {
public:
auto on_event(state_idle&,
const event_connect& e)
{ }
auto on_event(state_connecting&,
const event_connected&)
{ }
auto on_event(state_connecting& s,
const event_timeout&)
{
}
auto on_event(state_connected&,
const event_disconnect&)
{ }
template<typename State, typename Event>
auto on_event(State&, const Event&)
{ }
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions de ned by the FSM itself
48
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 88/108
class connection_fsm
: public fsm<connection_fsm, state> {
public:
auto on_event(state_idle&,
const event_connect& e)
{ return state_connecting{std::string(e.address)}; }
auto on_event(state_connecting&,
const event_connected&)
{ return state_connected{}; }
auto on_event(state_connecting& s,
const event_timeout&)
{
return ++s.n < state_connecting::n_max ?
std::nullopt : std::optional<state>(state_idle{});
}
auto on_event(state_connected&,
const event_disconnect&)
{ return state_idle{}; }
template<typename State, typename Event>
auto on_event(State&, const Event&)
{ return std::nullopt; }
};
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Transitions de ned by the FSM itself
48
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 89/108
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
Class diagram
49
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 90/108
What about performance?
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 91/108
CLOSED(Start)
LISTEN/-
CLOSE/-
LISTEN
SYN
RECEIVED
SYN
SENT
CONNECT/ (Step 1 of the 3-way-handshake)SYN
SYN/SYN+ACK(Step 2 of the 3-way-handshake)
unusual event
client/receiver path
server/sender path
RST/-
SYN/SYN+ACK (simultaneous open)
SYN+ACK/ACK
(Step 3 of the 3-way-handshake)
Data exchange occurs
ESTABLISHED
FIN/ACK
ACK/-
CLOSE/-
SEND/SYN
CLOSE/FIN
CLOSE/FIN
CLOSING
TIME WAIT
CLOSED
FIN WAIT 1
FIN WAIT 2
CLOSE WAIT
LAST ACK
CLOSE/FIN
FIN/ACK
FIN+ACK/ACK
ACK/-
FIN/ACK
Timeout
(Go back to start)
Active CLOSE Passive CLOSE
ACK/-
ACK/-
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
TCP state diagram
51
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 92/108
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
TCP FSM Performance
52
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 93/108
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
TCP FSM Performance
52
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 94/108
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
TCP FSM Performance
52
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 95/108
Summary
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 96/108
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
std::variant<Types...> vs inheritance
INHERITANCE VARIANT
54
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 97/108
• Open/Closed to new alternatives • Closed to new alternatives
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
std::variant<Types...> vs inheritance
INHERITANCE VARIANT
54
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 98/108
• Open/Closed to new alternatives
• Closed to new operations
• Closed to new alternatives
• Open to new operations
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
std::variant<Types...> vs inheritance
INHERITANCE VARIANT
54
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 99/108
• Open/Closed to new alternatives
• Closed to new operations
• Multi-level
• Closed to new alternatives
• Open to new operations
• Single level
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
std::variant<Types...> vs inheritance
INHERITANCE VARIANT
54
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 100/108
• Open/Closed to new alternatives
• Closed to new operations
• Multi-level
• OO
• Closed to new alternatives
• Open to new operations
• Single level
• Functional
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
std::variant<Types...> vs inheritance
INHERITANCE VARIANT
54
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 101/108
• Open/Closed to new alternatives
• Closed to new operations
• Multi-level
• OO
• Pointer semantics
• Closed to new alternatives
• Open to new operations
• Single level
• Functional
• Value semantics
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
std::variant<Types...> vs inheritance
INHERITANCE VARIANT
54
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 102/108
• Open/Closed to new alternatives
• Closed to new operations
• Multi-level
• OO
• Pointer semantics
• Design forced by the implementation details
• Closed to new alternatives
• Open to new operations
• Single level
• Functional
• Value semantics
• Many design choices possible
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
std::variant<Types...> vs inheritance
INHERITANCE VARIANT
54
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 103/108
• Open/Closed to new alternatives
• Closed to new operations
• Multi-level
• OO
• Pointer semantics
• Design forced by the implementation details
• Forces dynamic memory allocations
• Closed to new alternatives
• Open to new operations
• Single level
• Functional
• Value semantics
• Many design choices possible
• No dynamic memory allocations
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
std::variant<Types...> vs inheritance
INHERITANCE VARIANT
54
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 104/108
• Open/Closed to new alternatives
• Closed to new operations
• Multi-level
• OO
• Pointer semantics
• Design forced by the implementation details
• Forces dynamic memory allocations
• Strict interfaces
• Closed to new alternatives
• Open to new operations
• Single level
• Functional
• Value semantics
• Many design choices possible
• No dynamic memory allocations
• Duck typing
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
std::variant<Types...> vs inheritance
INHERITANCE VARIANT
54
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 105/108
• Open/Closed to new alternatives
• Closed to new operations
• Multi-level
• OO
• Pointer semantics
• Design forced by the implementation details
• Forces dynamic memory allocations
• Strict interfaces
• Complex
• Closed to new alternatives
• Open to new operations
• Single level
• Functional
• Value semantics
• Many design choices possible
• No dynamic memory allocations
• Duck typing
• Simple
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
std::variant<Types...> vs inheritance
INHERITANCE VARIANT
54
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 106/108
• Open/Closed to new alternatives
• Closed to new operations
• Multi-level
• OO
• Pointer semantics
• Design forced by the implementation details
• Forces dynamic memory allocations
• Strict interfaces
• Complex
• Slower
• Closed to new alternatives
• Open to new operations
• Single level
• Functional
• Value semantics
• Many design choices possible
• No dynamic memory allocations
• Duck typing
• Simple
• Faster
ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant
std::variant<Types...> vs inheritance
INHERITANCE VARIANT
54
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 107/108
12.04.2019 Effective replacement of dynamic polymorphism with std::variant
file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 108/108

More Related Content

PDF
Implementing Physical Units Library for C++
PDF
Effective replacement of dynamic polymorphism with std::variant
PDF
Model-Based Optimization for Effective and Reliable Decision-Making
PDF
Implementing Physical Units Library for C++. Mateusz Pusz.CoreHard Spring 2019
PDF
Implementing a Physical Units Library for C++
PDF
No more grid search! How to build models effectively by Thomas Huijskens
PPTX
HPC on Cloud for SMEs. The case of bolt tightening.
PDF
In Network Computing Prototype Using P4 at KSC/KREONET 2019
Implementing Physical Units Library for C++
Effective replacement of dynamic polymorphism with std::variant
Model-Based Optimization for Effective and Reliable Decision-Making
Implementing Physical Units Library for C++. Mateusz Pusz.CoreHard Spring 2019
Implementing a Physical Units Library for C++
No more grid search! How to build models effectively by Thomas Huijskens
HPC on Cloud for SMEs. The case of bolt tightening.
In Network Computing Prototype Using P4 at KSC/KREONET 2019

Similar to Effective replacement of dynamic polymorphism with std::variant (20)

PDF
APEX Interactive Grid API Essentials: The Stuff You Will Really Use
PDF
The future of thermoplastics in the automotive industry and process technolog...
PDF
S100294 bcdr-seven-tiers-orlando-v1804a
PDF
Feedback Driven Development
PDF
Characteristics of Remote Persistent Memory – Performance, Capacity, or Local...
PPTX
A challenge for thread parallelism on OpenFOAM
PPTX
Backend Cloud Storage Access in Video Streaming
PDF
An Introduction to Parallel Programming 2. Edition Pacheco
PPTX
Performance Computer Architecture Stuff.pptx
PDF
Towards Automated Boundary Value Testing with Program Derivatives and Search
PDF
Planning/Scheduling with CP Optimizer
PDF
The application of carbon fibre reinforced plastic in the automotive industry
PDF
S016386 business-continuity-melbourne-v1708c
PDF
S014072 business-continuity-orlando-v1705e
PDF
IBM XL Compilers Performance Tuning 2016-11-18
PDF
Introduction to HPC Programming Models - EUDAT Summer School (Stefano Markidi...
PDF
Machine Learning Meets Quantitative Planning: Enabling Self-Adaptation in Aut...
PDF
Sustainable applied innovation pankaj shah and bipin patwardhan cwin18 india
PDF
Collective Mind: a collaborative curation tool for program optimization
PDF
CK: from ad hoc computer engineering to collaborative and reproducible data s...
APEX Interactive Grid API Essentials: The Stuff You Will Really Use
The future of thermoplastics in the automotive industry and process technolog...
S100294 bcdr-seven-tiers-orlando-v1804a
Feedback Driven Development
Characteristics of Remote Persistent Memory – Performance, Capacity, or Local...
A challenge for thread parallelism on OpenFOAM
Backend Cloud Storage Access in Video Streaming
An Introduction to Parallel Programming 2. Edition Pacheco
Performance Computer Architecture Stuff.pptx
Towards Automated Boundary Value Testing with Program Derivatives and Search
Planning/Scheduling with CP Optimizer
The application of carbon fibre reinforced plastic in the automotive industry
S016386 business-continuity-melbourne-v1708c
S014072 business-continuity-orlando-v1705e
IBM XL Compilers Performance Tuning 2016-11-18
Introduction to HPC Programming Models - EUDAT Summer School (Stefano Markidi...
Machine Learning Meets Quantitative Planning: Enabling Self-Adaptation in Aut...
Sustainable applied innovation pankaj shah and bipin patwardhan cwin18 india
Collective Mind: a collaborative curation tool for program optimization
CK: from ad hoc computer engineering to collaborative and reproducible data s...
Ad

More from Mateusz Pusz (12)

PDF
Free Lunch is Over: Why is C++ so Important in the Modern World?
PDF
A Physical Units Library for the Next C++
PDF
Striving for ultimate Low Latency
PDF
Rethinking the Way We do Templates in C++
PDF
C++11 Was Only the Beginning
PDF
C++ Concepts and Ranges - How to use them?
PDF
Git, CMake, Conan - How to ship and reuse our C++ projects?
PDF
Beyond C++17
PDF
Pointless Pointers - How to make our interfaces efficient?
PDF
Striving for ultimate Low Latency
PDF
Small Lie in Big O
PDF
std::shared_ptr<T> - (not so) Smart hammer for every pointy nail
Free Lunch is Over: Why is C++ so Important in the Modern World?
A Physical Units Library for the Next C++
Striving for ultimate Low Latency
Rethinking the Way We do Templates in C++
C++11 Was Only the Beginning
C++ Concepts and Ranges - How to use them?
Git, CMake, Conan - How to ship and reuse our C++ projects?
Beyond C++17
Pointless Pointers - How to make our interfaces efficient?
Striving for ultimate Low Latency
Small Lie in Big O
std::shared_ptr<T> - (not so) Smart hammer for every pointy nail
Ad

Recently uploaded (20)

PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PPTX
A Presentation on Artificial Intelligence
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Approach and Philosophy of On baking technology
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Empathic Computing: Creating Shared Understanding
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Review of recent advances in non-invasive hemoglobin estimation
The Rise and Fall of 3GPP – Time for a Sabbatical?
Encapsulation_ Review paper, used for researhc scholars
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
MIND Revenue Release Quarter 2 2025 Press Release
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
A Presentation on Artificial Intelligence
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
gpt5_lecture_notes_comprehensive_20250812015547.pdf
sap open course for s4hana steps from ECC to s4
Unlocking AI with Model Context Protocol (MCP)
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Programs and apps: productivity, graphics, security and other tools
Building Integrated photovoltaic BIPV_UPV.pdf
Approach and Philosophy of On baking technology
Chapter 3 Spatial Domain Image Processing.pdf
Empathic Computing: Creating Shared Understanding
Advanced methodologies resolving dimensionality complications for autism neur...

Effective replacement of dynamic polymorphism with std::variant

  • 1. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 1/108 Mateusz Pusz April 12, 2019 E ective replacement of dynamic polymorphism with std::variant
  • 2. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 2/108 Why?
  • 3. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 3/108 • Time required to perform some action or to produce some result • Measured in units of time like hours, minutes, seconds, nanoseconds or clock periods ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Why? LATENCY 3
  • 4. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 4/108 • Time required to perform some action or to produce some result • Measured in units of time like hours, minutes, seconds, nanoseconds or clock periods • In capital markets, the use of algorithmic trading to react to market events faster than the competition to increase profitability of trades • Many use cases where predictability of latency in message delivery is just as important, if not more important than achieving a low average latency ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Why? LATENCY LOW LATENCY 3
  • 5. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 5/108 • In Low Latency system we care a lot about WCET (Worst Case Execution Time) • In order to limit WCET we should limit the usage of specific C++ language features ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant How NOT to develop software that have predictable performance? 4
  • 6. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 6/108 ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Things to avoid on the fast path 5
  • 7. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 7/108 • C++ tools that trade performance for usability (e.g. std::shared_ptr, std::function) ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Things to avoid on the fast path 5
  • 8. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 8/108 • C++ tools that trade performance for usability (e.g. std::shared_ptr, std::function) • Throwing exceptions on a likely code path ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Things to avoid on the fast path 5
  • 9. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 9/108 • C++ tools that trade performance for usability (e.g. std::shared_ptr, std::function) • Throwing exceptions on a likely code path • Dynamic polymorphism ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Things to avoid on the fast path 5
  • 10. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 10/108 • C++ tools that trade performance for usability (e.g. std::shared_ptr, std::function) • Throwing exceptions on a likely code path • Dynamic polymorphism • Multiple inheritance ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Things to avoid on the fast path 5
  • 11. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 11/108 • C++ tools that trade performance for usability (e.g. std::shared_ptr, std::function) • Throwing exceptions on a likely code path • Dynamic polymorphism • Multiple inheritance • RTTI ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Things to avoid on the fast path 5
  • 12. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 12/108 • C++ tools that trade performance for usability (e.g. std::shared_ptr, std::function) • Throwing exceptions on a likely code path • Dynamic polymorphism • Multiple inheritance • RTTI • Dynamic memory allocations ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Things to avoid on the fast path 5
  • 13. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 13/108 • Dynamic polymorphism • Dynamic memory allocations ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Things to avoid on the fast path • C++ tools that trade performance for usability (e.g. std::shared_ptr, std::function) • Throwing exceptions on a likely code path • Multiple inheritance • RTTI 6
  • 14. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 14/108 How?
  • 15. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 15/108 class base : noncopyable { public: virtual ~base() = default; virtual void foo() = 0; }; class x : public base { public: void foo() override; }; class y : public base { public: void foo() override; }; std::unique_ptr<base> b = std::make_unique<x>(); b->foo(); ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant How? DYNAMIC POLYMORPHISM 8
  • 16. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 16/108 class base : noncopyable { public: virtual ~base() = default; virtual void foo() = 0; }; class x : public base { public: void foo() override; }; class y : public base { public: void foo() override; }; std::unique_ptr<base> b = std::make_unique<x>(); b->foo(); ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant How? DYNAMIC POLYMORPHISM 8
  • 17. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 17/108 class base : noncopyable { public: virtual ~base() = default; virtual void foo() = 0; }; class x : public base { public: void foo() override; }; class y : public base { public: void foo() override; }; std::unique_ptr<base> b = std::make_unique<x>(); b->foo(); struct x { void foo(); }; struct y { void foo(); }; std::variant<x, y> b; std::visit([](auto&& v){ v.foo(); }, b); • Shorter • Faster • Value semantics • Works on unrelated classes • More flexible thanks to duck typing ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant How? DYNAMIC POLYMORPHISM VARIANT 8
  • 18. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 18/108 ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant THE END T H A N K Y O U ! 9
  • 19. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 19/108 Bonus slides
  • 20. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 20/108 Abstract machine that can be in exactly one of a finite number of states at any given time. -- Wikipedia ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Finite State Machine 11
  • 21. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 21/108 ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Finite State Machine 12
  • 22. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 22/108 • State changes to another in a response to some external inputs called events ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Finite State Machine 12
  • 23. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 23/108 • State changes to another in a response to some external inputs called events • The change from one state to another is called a transition ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Finite State Machine 12
  • 24. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 24/108 • State changes to another in a response to some external inputs called events • The change from one state to another is called a transition • A FSM is defined by – a list of states – its initial state – the conditions for each transition ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Finite State Machine 12
  • 25. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 25/108 Single dynamic dispatch CASE #1
  • 26. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 26/108 ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Class diagram 14
  • 27. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 27/108 template<typename Event> class state : noncopyable { public: virtual ~state() = default; virtual std::unique_ptr<state> on_event(Event) = 0; }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Single dynamic dispatch 15
  • 28. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 28/108 template<typename Event> class state : noncopyable { public: virtual ~state() = default; virtual std::unique_ptr<state> on_event(Event) = 0; }; template<typename Event> class fsm { std::unique_ptr<state<Event>> state_; public: explicit fsm(std::unique_ptr<state<Event>> state) : state_(std::move(state)) {} void dispatch(Event e) { auto new_state = state_->on_event(e); if(new_state) state_ = std::move(new_state); } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Single dynamic dispatch 15
  • 29. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 29/108 template<typename Event> class state : noncopyable { public: virtual ~state() = default; virtual std::unique_ptr<state> on_event(Event) = 0; }; template<typename Event> class fsm { std::unique_ptr<state<Event>> state_; public: explicit fsm(std::unique_ptr<state<Event>> state) : state_(std::move(state)) {} void dispatch(Event e) { auto new_state = state_->on_event(e); if(new_state) state_ = std::move(new_state); } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Single dynamic dispatch 16
  • 30. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 30/108 class connection_fsm : public fsm<event> { public: connection_fsm(): fsm<event>(std::make_unique<state_idle>()) {} }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Connection FSM 17
  • 31. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 31/108 class connection_fsm : public fsm<event> { public: connection_fsm(): fsm<event>(std::make_unique<state_idle>()) {} }; using s = state<event>; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Connection FSM 17
  • 32. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 32/108 class connection_fsm : public fsm<event> { public: connection_fsm(): fsm<event>(std::make_unique<state_idle>()) {} }; using s = state<event>; class state_idle final : public s { public: std::unique_ptr<s> on_event(event e) override; }; class state_connecting final : public s { static constexpr int n_max = 3; int n = 0; public: std::unique_ptr<s> on_event(event e) override; }; class state_connected final : public s { public: std::unique_ptr<s> on_event(event e) override; }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Connection FSM 17
  • 33. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 33/108 std::unique_ptr<s> state_idle::on_event(event e) { } std::unique_ptr<s> state_connecting::on_event(event e) { } std::unique_ptr<s> state_connected::on_event(event e) { } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 18
  • 34. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 34/108 std::unique_ptr<s> state_idle::on_event(event e) { if(e == event::connect) return std::make_unique<state_connecting>(); return nullptr; } std::unique_ptr<s> state_connecting::on_event(event e) { } std::unique_ptr<s> state_connected::on_event(event e) { } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 18
  • 35. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 35/108 std::unique_ptr<s> state_idle::on_event(event e) { if(e == event::connect) return std::make_unique<state_connecting>(); return nullptr; } std::unique_ptr<s> state_connecting::on_event(event e) { switch(e) { case event::connected: return std::make_unique<state_connected>(); case event::timeout: return ++n < n_max ? nullptr : std::make_unique<state_idle>(); default: return nullptr; } } std::unique_ptr<s> state_connected::on_event(event e) { } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 18
  • 36. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 36/108 std::unique_ptr<s> state_idle::on_event(event e) { if(e == event::connect) return std::make_unique<state_connecting>(); return nullptr; } std::unique_ptr<s> state_connecting::on_event(event e) { switch(e) { case event::connected: return std::make_unique<state_connected>(); case event::timeout: return ++n < n_max ? nullptr : std::make_unique<state_idle>(); default: return nullptr; } } std::unique_ptr<s> state_connected::on_event(event e) { if(e == event::disconnect) return std::make_unique<state_idle>(); return nullptr; } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 18
  • 37. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 37/108 std::unique_ptr<s> state_idle::on_event(event e) { if(e == event::connect) return std::make_unique<state_connecting>(); return nullptr; } std::unique_ptr<s> state_connecting::on_event(event e) { switch(e) { case event::connected: return std::make_unique<state_connected>(); case event::timeout: return ++n < n_max ? nullptr : std::make_unique<state_idle>(); default: return nullptr; } } std::unique_ptr<s> state_connected::on_event(event e) { if(e == event::disconnect) return std::make_unique<state_idle>(); return nullptr; } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant The slow part 19
  • 38. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 38/108 • Fold expressions come handy ;-) template<typename Fsm, typename... Events> void dispatch(Fsm& fsm, Events... events) { (fsm.dispatch(events), ...); } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Testing transitions 20
  • 39. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 39/108 • Fold expressions come handy ;-) template<typename Fsm, typename... Events> void dispatch(Fsm& fsm, Events... events) { (fsm.dispatch(events), ...); } • Simple message flow connection_fsm fsm; dispatch(fsm, event::connect, event::timeout, event::connected, event::disconnect); ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Testing transitions 20
  • 40. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 40/108 • Open to new alternatives – new derived types may be added by clients at any point of time (long a er base class implementation is finished) ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Single dynamic dispatch 21
  • 41. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 41/108 • Open to new alternatives – new derived types may be added by clients at any point of time (long a er base class implementation is finished) • Closed to new operations – clients cannot add new operations to dynamic dispatch ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Single dynamic dispatch 21
  • 42. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 42/108 • Open to new alternatives – new derived types may be added by clients at any point of time (long a er base class implementation is finished) • Closed to new operations – clients cannot add new operations to dynamic dispatch • Multi-level – many levels of inheritance possible ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Single dynamic dispatch 21
  • 43. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 43/108 • Open to new alternatives – new derived types may be added by clients at any point of time (long a er base class implementation is finished) • Closed to new operations – clients cannot add new operations to dynamic dispatch • Multi-level – many levels of inheritance possible • Object Oriented – whole framework is based on objects ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Single dynamic dispatch 21
  • 44. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 44/108 Double dynamic dispatch CASE #2
  • 45. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 45/108 class event : noncopyable { public: virtual ~event() = default; }; class event_connect final : public event { std::string_view address_; public: explicit event_connect(std::string_view address): address_(address) {} std::string_view address() const { return address_; } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant What if we want our events to pass data? 23
  • 46. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 46/108 class event : noncopyable { public: virtual ~event() = default; }; class event_connect final : public event { std::string_view address_; public: explicit event_connect(std::string_view address): address_(address) {} std::string_view address() const { return address_; } }; std::unique_ptr<state> state_idle::on_event(const event& e) { if(auto ptr = dynamic_cast<const event_connect*>(&e)) { /* ... */ } else { /* ... */ } } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant What if we want our events to pass data? 23
  • 47. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 47/108 class event : noncopyable { public: virtual ~event() = default; }; class event_connect final : public event { std::string_view address_; public: explicit event_connect(std::string_view address): address_(address) {} std::string_view address() const { return address_; } }; std::unique_ptr<state> state_idle::on_event(const event& e) { if(auto ptr = dynamic_cast<const event_connect*>(&e)) { /* ... */ } else { /* ... */ } } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant What if we want our events to pass data? A really bad idea :-( 23
  • 48. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 48/108 Special form of multiple dispatch, and a mechanism that dispatches a function call to di erent concrete functions depending on the runtime types of two objects involved in the call -- Wikipedia ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Double dispatch (aka Visitor Pattern) 24
  • 49. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 49/108 template<typename State> struct event : private noncopyable { virtual ~event() = default; virtual std::unique_ptr<State> dispatch(State& s) const = 0; }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Double dispatch (aka Visitor Pattern) 25
  • 50. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 50/108 template<typename State> struct event : private noncopyable { virtual ~event() = default; virtual std::unique_ptr<State> dispatch(State& s) const = 0; }; template<typename State, typename Event> class fsm { std::unique_ptr<State> state_; public: explicit fsm(std::unique_ptr<State> state) : state_(std::move(state)) {} void dispatch(const Event& e) { auto new_state = e.dispatch(*state_); if(new_state) state_ = std::move(new_state); } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Double dispatch (aka Visitor Pattern) 25
  • 51. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 51/108 template<typename State> struct event : private noncopyable { virtual ~event() = default; virtual std::unique_ptr<State> dispatch(State& s) const = 0; }; struct event_connect final : public event<state> { std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); } // ... }; struct event_connected final : public event<state> { std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); } }; struct event_disconnect final : public event<state> { std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); } }; struct event_timeout final : public event<state> { std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Double dispatch (aka Visitor Pattern) 26
  • 52. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 52/108 template<typename State> struct event : private noncopyable { virtual ~event() = default; virtual std::unique_ptr<State> dispatch(State& s) const = 0; }; class state : noncopyable { public: virtual ~state() = default; virtual std::unique_ptr<state> on_event(const event_connect&) { return nullptr; } virtual std::unique_ptr<state> on_event(const event_connected&) { return nullptr; } virtual std::unique_ptr<state> on_event(const event_disconnect&) { return nullptr; } virtual std::unique_ptr<state> on_event(const event_timeout&) { return nullptr; } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Double dispatch (aka Visitor Pattern) 27
  • 53. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 53/108 template<typename State> struct event : private noncopyable { virtual ~event() = default; virtual std::unique_ptr<State> dispatch(State& s) const = 0; }; class state : noncopyable { public: virtual ~state() = default; virtual std::unique_ptr<state> on_event(const event_connect&) { return nullptr; } virtual std::unique_ptr<state> on_event(const event_connected&) { return nullptr; } virtual std::unique_ptr<state> on_event(const event_disconnect&) { return nullptr; } virtual std::unique_ptr<state> on_event(const event_timeout&) { return nullptr; } }; class state_idle final : public state { public: using state::on_event; std::unique_ptr<state> on_event(const event_connect& e) override { return std::make_unique<state_connecting>(std::string(e.address())); } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Double dispatch (aka Visitor Pattern) 27
  • 54. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 54/108 ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Class diagram 28
  • 55. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 55/108 template<typename State> struct event : private noncopyable { virtual ~event() = default; virtual std::unique_ptr<State> dispatch(State& s) const = 0; }; struct event_connect final : public event<state> { std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); } // ... }; struct event_connected final : public event<state> { std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); } }; struct event_disconnect final : public event<state> { std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); } }; struct event_timeout final : public event<state> { std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*this); } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Curiously Recurring Template Pattern (CRTP) 29
  • 56. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 56/108 template<typename State> struct event : private noncopyable { virtual ~event() = default; virtual std::unique_ptr<State> dispatch(State& s) const = 0; }; template<typename Child> struct event_crtp : event<state> { std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*static_cast<const Child*>(this)); } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Curiously Recurring Template Pattern (CRTP) 30
  • 57. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 57/108 template<typename State> struct event : private noncopyable { virtual ~event() = default; virtual std::unique_ptr<State> dispatch(State& s) const = 0; }; template<typename Child> struct event_crtp : event<state> { std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*static_cast<const Child*>(this)); } }; struct event_connect final : public event_crtp<event_connect> { // ... }; struct event_connected final : public event_crtp<event_connected> {}; struct event_disconnect final : public event_crtp<event_disconnect> {}; struct event_timeout final : public event_crtp<event_timeout> {}; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Curiously Recurring Template Pattern (CRTP) 30
  • 58. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 58/108 template<typename State> struct event : private noncopyable { virtual ~event() = default; virtual std::unique_ptr<State> dispatch(State& s) const = 0; }; template<typename Child> struct event_crtp : event<state> { std::unique_ptr<state> dispatch(state& s) const override { return s.on_event(*static_cast<const Child*>(this)); } }; struct event_connect final : public event_crtp<event_connect> { explicit event_connect(std::string_view address): address_(address) {} std::string_view address() const { return address_; } private: std::string_view address_; }; struct event_connected final : public event_crtp<event_connected> {}; struct event_disconnect final : public event_crtp<event_disconnect> {}; struct event_timeout final : public event_crtp<event_timeout> {}; • Hey look ma, now all fits on one slide ;-) ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Curiously Recurring Template Pattern (CRTP) 31
  • 59. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 59/108 std::unique_ptr<state> state_idle::on_event(const event_connect& e) { } std::unique_ptr<state> state_connecting::on_event(const event_connected&) { } std::unique_ptr<state> state_connecting::on_event(const event_timeout&) { } std::unique_ptr<state> state_connected::on_event(const event_disconnect&) { } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 32
  • 60. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 60/108 std::unique_ptr<state> state_idle::on_event(const event_connect& e) { return std::make_unique<state_connecting>( std::string{e.address()}); } std::unique_ptr<state> state_connecting::on_event(const event_connected&) { } std::unique_ptr<state> state_connecting::on_event(const event_timeout&) { } std::unique_ptr<state> state_connected::on_event(const event_disconnect&) { } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 32
  • 61. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 61/108 std::unique_ptr<state> state_idle::on_event(const event_connect& e) { return std::make_unique<state_connecting>( std::string{e.address()}); } std::unique_ptr<state> state_connecting::on_event(const event_connected&) { return std::make_unique<state_connected>(); } std::unique_ptr<state> state_connecting::on_event(const event_timeout&) { } std::unique_ptr<state> state_connected::on_event(const event_disconnect&) { } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 32
  • 62. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 62/108 std::unique_ptr<state> state_idle::on_event(const event_connect& e) { return std::make_unique<state_connecting>( std::string{e.address()}); } std::unique_ptr<state> state_connecting::on_event(const event_connected&) { return std::make_unique<state_connected>(); } std::unique_ptr<state> state_connecting::on_event(const event_timeout&) { return ++n < n_max ? nullptr : std::make_unique<state_idle>(); } std::unique_ptr<state> state_connected::on_event(const event_disconnect&) { } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 32
  • 63. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 63/108 std::unique_ptr<state> state_idle::on_event(const event_connect& e) { return std::make_unique<state_connecting>( std::string{e.address()}); } std::unique_ptr<state> state_connecting::on_event(const event_connected&) { return std::make_unique<state_connected>(); } std::unique_ptr<state> state_connecting::on_event(const event_timeout&) { return ++n < n_max ? nullptr : std::make_unique<state_idle>(); } std::unique_ptr<state> state_connected::on_event(const event_disconnect&) { return std::make_unique<state_idle>(); } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 32
  • 64. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 64/108 std::unique_ptr<state> state_idle::on_event(const event_connect& e) { return std::make_unique<state_connecting>( std::string{e.address()}); } std::unique_ptr<state> state_connecting::on_event(const event_connected&) { return std::make_unique<state_connected>(); } std::unique_ptr<state> state_connecting::on_event(const event_timeout&) { return ++n < n_max ? nullptr : std::make_unique<state_idle>(); } std::unique_ptr<state> state_connected::on_event(const event_disconnect&) { return std::make_unique<state_idle>(); } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant The slow part 33
  • 65. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 65/108 template<typename Fsm, typename... Events> void dispatch(Fsm& fsm, const Events&... events) { (fsm.dispatch(*events), ...); } ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Testing transitions 34
  • 66. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 66/108 template<typename Fsm, typename... Events> void dispatch(Fsm& fsm, const Events&... events) { (fsm.dispatch(*events), ...); } dispatch(fsm, std::make_unique<event_connect>("train-it.eu"), std::make_unique<event_timeout>(), std::make_unique<event_connected>(), std::make_unique<event_disconnect>()); ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Testing transitions 34
  • 67. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 67/108 template<typename Fsm, typename... Events> void dispatch(Fsm& fsm, const Events&... events) { (fsm.dispatch(*events), ...); } dispatch(fsm, std::make_unique<event_connect>("train-it.eu"), std::make_unique<event_timeout>(), std::make_unique<event_connected>(), std::make_unique<event_disconnect>()); ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant The slow part 35
  • 68. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 68/108 • Open to new alternatives • Closed to new alternatives – one of class hierarchies fixed at design time and cannot be extended by clients • Closed to new operations – clients cannot add new operations to dynamic dispatch • Multi-level – many levels of inheritance possible • Object Oriented – whole framework is based on objects ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Double dynamic dispatch (aka Visitor Pattern) 36
  • 69. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 69/108 Variant + external transitions CASE #3
  • 70. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 70/108 struct event_connect { std::string_view address; }; struct event_connected {}; struct event_disconnect {}; struct event_timeout {}; using event = std::variant<event_connect, event_connected, event_disconnect, event_timeout>; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Events and states EVENTS 38
  • 71. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 71/108 struct event_connect { std::string_view address; }; struct event_connected {}; struct event_disconnect {}; struct event_timeout {}; using event = std::variant<event_connect, event_connected, event_disconnect, event_timeout>; struct state_idle {}; struct state_connecting { static constexpr int n_max = 3; int n = 0; std::string address; }; struct state_connected {}; using state = std::variant<state_idle, state_connecting, state_connected>; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Events and states EVENTS STATES 38
  • 72. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 72/108 struct transitions { optional<state> operator()(state_idle&, const event_connect& e) { } optional<state> operator()(state_connecting&, const event_connected&) { } optional<state> operator()(state_connecting& s, const event_timeout&) { } optional<state> operator()(state_connected&, const event_disconnect&) { } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 39
  • 73. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 73/108 struct transitions { optional<state> operator()(state_idle&, const event_connect& e) { return state_connecting{std::string(e.address)}; } optional<state> operator()(state_connecting&, const event_connected&) { } optional<state> operator()(state_connecting& s, const event_timeout&) { } optional<state> operator()(state_connected&, const event_disconnect&) { } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 39
  • 74. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 74/108 struct transitions { optional<state> operator()(state_idle&, const event_connect& e) { return state_connecting{std::string(e.address)}; } optional<state> operator()(state_connecting&, const event_connected&) { return state_connected{}; } optional<state> operator()(state_connecting& s, const event_timeout&) { } optional<state> operator()(state_connected&, const event_disconnect&) { } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 39
  • 75. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 75/108 struct transitions { optional<state> operator()(state_idle&, const event_connect& e) { return state_connecting{std::string(e.address)}; } optional<state> operator()(state_connecting&, const event_connected&) { return state_connected{}; } optional<state> operator()(state_connecting& s, const event_timeout&) { return ++s.n < state_connecting::n_max ? std::nullopt : optional<state>(state_idle{}); } optional<state> operator()(state_connected&, const event_disconnect&) { } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 39
  • 76. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 76/108 struct transitions { optional<state> operator()(state_idle&, const event_connect& e) { return state_connecting{std::string(e.address)}; } optional<state> operator()(state_connecting&, const event_connected&) { return state_connected{}; } optional<state> operator()(state_connecting& s, const event_timeout&) { return ++s.n < state_connecting::n_max ? std::nullopt : optional<state>(state_idle{}); } optional<state> operator()(state_connected&, const event_disconnect&) { return state_idle{}; } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 39
  • 77. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 77/108 struct transitions { optional<state> operator()(state_idle&, const event_connect& e) { return state_connecting{std::string(e.address)}; } optional<state> operator()(state_connecting&, const event_connected&) { return state_connected{}; } optional<state> operator()(state_connecting& s, const event_timeout&) { return ++s.n < state_connecting::n_max ? std::nullopt : optional<state>(state_idle{}); } optional<state> operator()(state_connected&, const event_disconnect&) { return state_idle{}; } template<typename State, typename Event> optional<state> operator()(State&, const Event&) const { return std::nullopt; } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions 39
  • 78. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 78/108 template<typename StateVariant, typename EventVariant, typename Transitions> class fsm { StateVariant state_; public: void dispatch(const EventVariant& event) { std::optional<StateVariant> new_state = std::visit(Transitions{}, state_, event); if(new_state) state_ = *std::move(new_state); } }; using connection_fsm = fsm<state, event, transitions>; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant FSM engine 40
  • 79. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 79/108 template<typename StateVariant, typename EventVariant, typename Transitions> class fsm { StateVariant state_; public: void dispatch(const EventVariant& event) { std::optional<StateVariant> new_state = std::visit(Transitions{}, state_, event); if(new_state) state_ = *std::move(new_state); } }; using connection_fsm = fsm<state, event, transitions>; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant FSM engine 41
  • 80. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 80/108 template<typename StateVariant, typename EventVariant, typename Transitions> class fsm { StateVariant state_; public: void dispatch(const EventVariant& event) { std::optional<StateVariant> new_state = std::visit(Transitions{}, state_, event); if(new_state) state_ = *std::move(new_state); } }; using connection_fsm = fsm<state, event, transitions>; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant FSM engine 42
  • 81. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 81/108 ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Class diagram 43
  • 82. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 82/108 template<typename Fsm, typename... Events> void dispatch(Fsm& fsm, Events&&... events) { (fsm.dispatch(std::forward<Events>(events)), ...); } dispatch(fsm, event_connect{"train-it.eu"}, event_timeout{}, event_connected{}, event_disconnect{}); ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Testing transitions 44
  • 83. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 83/108 Variant + transitions in FSM CASE #4
  • 84. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 84/108 template<typename Derived, typename StateVariant, typename EventVariant> class fsm { StateVariant state_; public: void dispatch(const EventVariant& event) { auto new_state = std::visit( state_, event); if(new_state) state_ = *std::move(new_state); } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant FSM engine 46
  • 85. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 85/108 template<typename Derived, typename StateVariant, typename EventVariant> class fsm { StateVariant state_; public: void dispatch(const EventVariant& event) { Derived& child = static_cast<Derived&>(*this); auto new_state = std::visit( [&](auto& s, const auto& e) -> std::optional<StateVariant> { return child.on_event(s, e); }, state_, event); if(new_state) state_ = *std::move(new_state); } }; • CRTP again ;-) ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant FSM engine 46
  • 86. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 86/108 template<typename Derived, typename StateVariant> class fsm { StateVariant state_; public: template<typename Event> void dispatch(Event&& event) { Derived& child = static_cast<Derived&>(*this); auto new_state = std::visit( [&](auto& s) -> std::optional<StateVariant> { return child.on_event(s, std::forward<Event>(event)); }, state_); if(new_state) state_ = *std::move(new_state); } }; • Visitation on a StateVariant only ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant FSM engine: dispatch() as an overload set 47
  • 87. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 87/108 class connection_fsm : public fsm<connection_fsm, state> { public: auto on_event(state_idle&, const event_connect& e) { } auto on_event(state_connecting&, const event_connected&) { } auto on_event(state_connecting& s, const event_timeout&) { } auto on_event(state_connected&, const event_disconnect&) { } template<typename State, typename Event> auto on_event(State&, const Event&) { } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions de ned by the FSM itself 48
  • 88. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 88/108 class connection_fsm : public fsm<connection_fsm, state> { public: auto on_event(state_idle&, const event_connect& e) { return state_connecting{std::string(e.address)}; } auto on_event(state_connecting&, const event_connected&) { return state_connected{}; } auto on_event(state_connecting& s, const event_timeout&) { return ++s.n < state_connecting::n_max ? std::nullopt : std::optional<state>(state_idle{}); } auto on_event(state_connected&, const event_disconnect&) { return state_idle{}; } template<typename State, typename Event> auto on_event(State&, const Event&) { return std::nullopt; } }; ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Transitions de ned by the FSM itself 48
  • 89. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 89/108 ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant Class diagram 49
  • 90. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 90/108 What about performance?
  • 91. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 91/108 CLOSED(Start) LISTEN/- CLOSE/- LISTEN SYN RECEIVED SYN SENT CONNECT/ (Step 1 of the 3-way-handshake)SYN SYN/SYN+ACK(Step 2 of the 3-way-handshake) unusual event client/receiver path server/sender path RST/- SYN/SYN+ACK (simultaneous open) SYN+ACK/ACK (Step 3 of the 3-way-handshake) Data exchange occurs ESTABLISHED FIN/ACK ACK/- CLOSE/- SEND/SYN CLOSE/FIN CLOSE/FIN CLOSING TIME WAIT CLOSED FIN WAIT 1 FIN WAIT 2 CLOSE WAIT LAST ACK CLOSE/FIN FIN/ACK FIN+ACK/ACK ACK/- FIN/ACK Timeout (Go back to start) Active CLOSE Passive CLOSE ACK/- ACK/- ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant TCP state diagram 51
  • 92. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 92/108 ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant TCP FSM Performance 52
  • 93. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 93/108 ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant TCP FSM Performance 52
  • 94. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 94/108 ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant TCP FSM Performance 52
  • 95. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 95/108 Summary
  • 96. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 96/108 ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant std::variant<Types...> vs inheritance INHERITANCE VARIANT 54
  • 97. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 97/108 • Open/Closed to new alternatives • Closed to new alternatives ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant std::variant<Types...> vs inheritance INHERITANCE VARIANT 54
  • 98. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 98/108 • Open/Closed to new alternatives • Closed to new operations • Closed to new alternatives • Open to new operations ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant std::variant<Types...> vs inheritance INHERITANCE VARIANT 54
  • 99. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 99/108 • Open/Closed to new alternatives • Closed to new operations • Multi-level • Closed to new alternatives • Open to new operations • Single level ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant std::variant<Types...> vs inheritance INHERITANCE VARIANT 54
  • 100. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 100/108 • Open/Closed to new alternatives • Closed to new operations • Multi-level • OO • Closed to new alternatives • Open to new operations • Single level • Functional ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant std::variant<Types...> vs inheritance INHERITANCE VARIANT 54
  • 101. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 101/108 • Open/Closed to new alternatives • Closed to new operations • Multi-level • OO • Pointer semantics • Closed to new alternatives • Open to new operations • Single level • Functional • Value semantics ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant std::variant<Types...> vs inheritance INHERITANCE VARIANT 54
  • 102. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 102/108 • Open/Closed to new alternatives • Closed to new operations • Multi-level • OO • Pointer semantics • Design forced by the implementation details • Closed to new alternatives • Open to new operations • Single level • Functional • Value semantics • Many design choices possible ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant std::variant<Types...> vs inheritance INHERITANCE VARIANT 54
  • 103. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 103/108 • Open/Closed to new alternatives • Closed to new operations • Multi-level • OO • Pointer semantics • Design forced by the implementation details • Forces dynamic memory allocations • Closed to new alternatives • Open to new operations • Single level • Functional • Value semantics • Many design choices possible • No dynamic memory allocations ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant std::variant<Types...> vs inheritance INHERITANCE VARIANT 54
  • 104. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 104/108 • Open/Closed to new alternatives • Closed to new operations • Multi-level • OO • Pointer semantics • Design forced by the implementation details • Forces dynamic memory allocations • Strict interfaces • Closed to new alternatives • Open to new operations • Single level • Functional • Value semantics • Many design choices possible • No dynamic memory allocations • Duck typing ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant std::variant<Types...> vs inheritance INHERITANCE VARIANT 54
  • 105. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 105/108 • Open/Closed to new alternatives • Closed to new operations • Multi-level • OO • Pointer semantics • Design forced by the implementation details • Forces dynamic memory allocations • Strict interfaces • Complex • Closed to new alternatives • Open to new operations • Single level • Functional • Value semantics • Many design choices possible • No dynamic memory allocations • Duck typing • Simple ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant std::variant<Types...> vs inheritance INHERITANCE VARIANT 54
  • 106. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 106/108 • Open/Closed to new alternatives • Closed to new operations • Multi-level • OO • Pointer semantics • Design forced by the implementation details • Forces dynamic memory allocations • Strict interfaces • Complex • Slower • Closed to new alternatives • Open to new operations • Single level • Functional • Value semantics • Many design choices possible • No dynamic memory allocations • Duck typing • Simple • Faster ACCU 2019 | E ective replacement of dynamic polymorphism with std::variant std::variant<Types...> vs inheritance INHERITANCE VARIANT 54
  • 107. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 107/108
  • 108. 12.04.2019 Effective replacement of dynamic polymorphism with std::variant file:///C:/repos/cppTrainings/build/out/polymorphism_with_variant/polymorphism_with_variant.html#108 108/108