SlideShare a Scribd company logo
New Tools for a More
Functional C++
Sumant Tambe
Sr. Software Engineer, LinkedIn
Microsoft MVP
SF Bay Area ACCU
Sept 28, 2017
Blogger (since 2005)
Coditation—Elegant Code for Big Data
Author (wikibook) Open-source contributor
Since 2013 (Visual Studio and Dev Tech)
Functional Programming
in C++
by Ivan Cukic
(ETA early 2018)
Reviewer
Sum Types and (pseudo) Pattern Matching
Modeling Alternatives
Inheritance vs std::variant
• States of a game of Tennis
• NormalScore
• DeuceScore
• AdvantageScore
• GameCompleteScore
Modeling game states using std::variant
struct NormalScore {
Player p1, p2;
int p1_score, p2_score;
};
struct DeuceScore {
Player p1, p2;
};
struct AdvantageScore {
Player lead, lagging;
};
struct GameCompleteScore {
Player winner, loser;
int loser_score;
};
using GameState = std::variant<NormalScore, DeuceScore,
AdvantageScore, GameCompleteScore>;
Print GameState (std::variant)
struct GameStatePrinter {
std::ostream &o;
explicit GameStatePrinter(std::ostream& out) : o(out) {}
void operator ()(const NormalScore& ns) const {
o << "NormalScore[" << ns.p1 << ns.p2 << ns.p1_score << ns.p2_score << "]";
}
void operator ()(const DeuceScore& ds) const {
o << "DeuceScore[" << ds.p1 << "," << ds.p2 << "]";
}
void operator ()(const AdvantageScore& as) const {
o << "AdvantageScore[" << as.lead << "," << as.lagging << "]";
}
void operator ()(const GameCompleteScore& gc) const {
o << "GameComplete[" << gc.winner << gc.loser << gc.loser_score << "]";
}
};
std::ostream & operator << (std::ostream& o, const GameState& game) {
std::visit(GameStatePrinter(o), game);
return o;
}
std::visit spews blood when you miss a case
Print GameState. Fancier!
std::ostream & operator << (std::ostream& o, const GameState& game) {
std::visit(overloaded {
[&](const NormalScore& ns) {
o << "NormalScore" << ns.p1 << ns.p2 << ns.p1_score << ns.p2_score;
},
[&](const DeuceScore& gc) {
o << "DeuceScore[" << ds.p1 << "," << ds.p2 << "]";
},
[&](const AdvantageScore& as) {
o << "AdvantageScore[" << as.lead << "," << as.lagging << "]";
},
[&](const GameCompleteScore& gc) {
o << "GameComplete[" << gc.winner << gc.loser << gc.loser_score << "]";
}
}, game);
return o;
}
Passing Two Variants to std::visit
std::ostream & operator << (std::ostream& o, const GameState& game) {
std::visit(overloaded {
[&](const NormalScore& ns, const auto& other) {
o << "NormalScore" << ns.p1 << ns.p2 << ns.p1_score << ns.p2_score;
},
[&](const DeuceScore& gc, const auto& other) {
o << "DeuceScore[" << ds.p1 << "," << ds.p2 << "]";
},
[&](const AdvantageScore& as, const auto& other) {
o << "AdvantageScore[" << as.lead << "," << as.lagging << "]";
},
[&](const GameCompleteScore& gc, const auto& other) {
o << "GameComplete[" << gc.winner << gc.loser << gc.loser_score << "]";
}
}, game, someother_variant);
return o;
}
There can be arbitrary number of arbitrary variant types.
The visitor must cover all cases
A Template to Inherit Lambdas
template <class... Ts>
struct overloaded : Ts... {
using Ts::operator()...;
explicit overloaded(Ts... ts) : Ts(ts)... {}
};
A User-Defined Deduction Guide
explicit overloaded(Ts... ts) : Ts(ts)... {}
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
Next GameState Algorithm (all cases in one place)
GameState next (const GameState& now,
const Player& who_scored)
{
return std::visit(overloaded {
[&](const DeuceScore& ds) -> GameState {
if (ds.p1 == who_scored)
return AdvantageScore{ds.p1, ds.p2};
else
return AdvantageScore{ds.p2, ds.p1};
},
[&](const AdvantageScore& as) -> GameState {
if (as.lead == who_scored)
return GameCompleteScore{as.lead, as.lagging, 40};
else
return DeuceScore{as.lead, as.lagging};
},
[&](const GameCompleteScore &) -> GameState {
throw "Illegal State";
},
[&](const NormalScore& ns) -> GameState {
if (ns.p1 == who_scored) {
switch (ns.p1_score) {
case 0: return NormalScore{ns.p1, ns.p2, 15, ns.p2_score};
case 15: return NormalScore{ns.p1, ns.p2, 30, ns.p2_score};
case 30: if (ns.p2_score < 40)
return NormalScore{ns.p1, ns.p2, 40, ns.p2_score};
else
return DeuceScore{ns.p1, ns.p2};
case 40: return GameCompleteScore{ns.p1, ns.p2, ns.p2_score};
default: throw "Makes no sense!";
}
}
else {
switch (ns.p2_score) {
case 0: return NormalScore{ns.p1, ns.p2, ns.p1_score, 15};
case 15: return NormalScore{ns.p1, ns.p2, ns.p1_score, 30};
case 30: if (ns.p1_score < 40)
return NormalScore{ns.p1, ns.p2, ns.p1_score, 40};
else
return DeuceScore{ns.p1, ns.p2};
case 40: return GameCompleteScore{ns.p2, ns.p1, ns.p1_score};
default: throw "Makes no sense!";
}
}
}
}, now);
}
Modeling Alternatives with Inheritance
class GameState {
std::unique_ptr<GameStateImpl> _state;
public:
void next(const Player& who_scored) {}
};
class GameStateImpl {
Player p1, p2;
public:
virtual GameStateImpl * next(
const Player& who_scored) = 0;
virtual ~GameStateImpl(){}
};
class NormalScore : public GameStateImpl {
int p1_score, p2_score;
public:
GameStateImpl * next(const Player&);
};
class DeuceScore : public GameStateImpl {
public:
GameStateImpl * next(const Player&);
};
class AdvantageScore : public GameStateImpl {
int lead;
public:
GameStateImpl * next(const Player&);
};
class GameCompleteScore :public GameStateImpl{
int winner, loser_score;
public:
GameStateImpl * next(const Player&);
};
Sharing State is easier with Inheritance
class GameState {
std::unique_ptr<GameStateImpl> _state;
public:
void next(const Player& who_scored) {}
Player& who_is_serving() const;
double fastest_serve_speed() const;
GameState get_last_state() const;
};
class GameStateImpl {
Player p1, p2;
int serving_player;
double speed;
GameState last_state;
public:
virtual GameStateImpl * next(
const Player& who_scored) = 0;
virtual Player& who_is_serving() const;
virtual double fastest_serve_speed() const;
virtual GameState get_last_state() const;
};
Sharing Common State is Repetitive with std::variant
Player who_is_serving = std::visit([](auto& s) {
return s.who_is_serving();
}, state);
Player who_is_serving = state.who_is_serving();
ceremony!
struct NormalScore {
Player p1, p2;
int p1_score, p2_score;
int serving_player;
Player & who_is_serving();
};
struct DeuceScore {
Player p1, p2;
int serving_player;
Player & who_is_serving();
};
struct AdvantageScore {
Player lead, lagging;
int serving_player;
Player & who_is_serving();
};
struct GameCompleteScore {
Player winner, loser;
int loser_score;
int serving_player;
Player & who_is_serving();
};
How about recursive std::variant?
struct NormalScore {
Player p1, p2;
int p1_score, p2_score;
int serving_player;
Player & who_is_serving();
GameState last_state;
};
struct DeuceScore {
Player p1, p2;
int serving_player;
Player & who_is_serving();
GameState last_state;
};
struct AdvantageScore {
Player lead, lagging;
int serving_player;
Player & who_is_serving();
GameState last_state;
};
struct GameCompleteScore {
Player winner, loser;
int loser_score;
int serving_player;
Player & who_is_serving();
GameState last_state;
};
Not possible unless you use recursive_wrapper and dynamic allocation.
Not in C++17.
Dare I say, it’s not algebraic? It does not compose 
std::variant is a container. Not an abstraction.
std::variant disables fluent interfaces
{
using GameState = std::variant<NormalScore, DeuceScore,
AdvantageScore, GameCompleteScore>;
GameState state = NormalScore {..};
GameState last_state = std::visit([](auto& s) {
return s.get_last_state();
}, state);
double last_speed = std::visit([](auto& s) {
return state.fastest_serve_speed();
}, last_state);
double last_speed = state.get_last_state().fastest_serve_speed();
}
ceremony!
Combine Implementation Inheritance with
std::variant
{
using GameState = std::variant<NormalScore_v2, DeuceScore_v2,
AdvantageScore_v2, GameCompleteScore_v2>;
GameState state = NormalScore_v2 {..};
Player who_is_serving = std::visit([](SharedGameState& s) {
return s.who_is_serving();
}, state);
Player who_is_serving = state.who_is_serving();
}
SharedGameState
who_is_serving()
NormalScore_v2 DeuceScore_v2 AdvantageScore_v2 GameCompleteScore_v2
ceremony!
Modeling Alternatives
Inheritance std::variant
Dynamic Allocation No dynamic allocation
Intrusive Non-intrusive
Reference semantics (how will you copy a
vector?)
Value semantics
Algorithm scattered into classes Algorithm in one place
Language supported
Clear errors if pure-virtual is not implemented
Library supported
std::visit spews blood on missing cases
Creates a first-class abstraction It’s just a container
Keeps fluent interfaces Disables fluent interfaces. Repeated std::visit
Supports recursive types (Composite) Must use recursive_wrapper and dynamic
allocation. Not in the C++17 standard.
Deep Immutability
const is shallow
struct X {
void bar();
};
struct Y {
X* xptr;
explicit Y(X* x) : xptr(x) {}
void foo() const {
xptr->bar();
}
};
{
const Y y(new X);
y.foo(); // mutates X??
}
Deep Immutability: propagate_const<T>
struct X {
void bar();
void bar() const; // Compiler error without this function
};
struct Y {
X* xptr;
propagate_const<X *> xptr;
explicit Y(X* x) : xptr(x) {}
void foo() const {
xptr->bar();
}
};
{
const Y y(new X);
y.foo(); // calls X.bar() const
}
Deep Immutability: propagate_const<T>
#include <experimental/propagate_const>
using std::experimental::propagate_const;
{
propagate_const<X *> xptr;
propagate_const<std::unique_ptr<X>> uptr;
propagate_const<std::shared_ptr<X>> shptr;
const propagate_const<std::shared_ptr<X>> c_shptr;
shptr.get() === X*
c_shptr.get() === const X*
*shptr === X&
*c_shptr === const X&
get_underlying(shptr) === shared_ptr<X>
get_underlying(c_shptr) === const shared_ptr<X>
shptr = another_shptr; // Error. Not copy-assignable
shptr = std::move(another_shptr) // but movable
Library fundamental TS v2
Mutable Temporaries
The Named Parameter Idiom (mutable)
class configs {
std::string server;
std::string protocol;
public:
configs & set_server(const std::string& s);
configs & set_protocol(const std::string& s);
};
start_server(configs().set_server(“localhost”)
.set_protocol(“https”));
The Named Parameter Idiom (immutable)
class configs {
public:
configs set_server(const std::string& s) const {
configs temp(*this); temp.server = s; return temp;
}
configs set_protocol(const std::string& proto) const {
configs temp(*this); temp.protocol = proto; return temp;
}
};
start_server(configs().set_server(“localhost”)
.set_protocol(“https”));
Avoid
copy-constructors?
The Named Parameter Idiom (immutable*)
class configs {
public:
configs set_server(const std::string& s) const {
configs temp(*this); temp.server = s; return temp;
}
configs set_protocol(const std::string& proto) const {
configs temp(*this); temp.protocol = proto; return temp;
}
configs set_server(const std::string& s) && {
server = s; return *this;
}
configs set_protocol(const std::string& proto) && {
protocol = proto; return *this;
}
};
start_server(configs().set_server(“localhost”)
.set_protocol(“https”));
&
&
The Named Parameter Idiom (immutable*)
class configs {
public:
configs set_server(const std::string& s) const {
configs temp(*this); temp.server = s; return temp;
}
configs set_protocol(const std::string& proto) const {
configs temp(*this); temp.protocol = proto; return temp;
}
configs&& set_server(const std::string& s) && {
server = s; return *this; std::move(*this);
}
configs&& set_protocol(const std::string& proto) && {
protocol = proto; return *this; std::move(*this);
}
};
start_server(configs().set_server(“localhost”)
.set_protocol(“https”));
&
&
Thank You!

More Related Content

Similar to New Tools for a More Functional C++

C++You will design a program to play a simplified version of war, .pdf
C++You will design a program to play a simplified version of war, .pdfC++You will design a program to play a simplified version of war, .pdf
C++You will design a program to play a simplified version of war, .pdf
ezzi97
 
The Ring programming language version 1.5 book - Part 9 of 31
The Ring programming language version 1.5 book - Part 9 of 31The Ring programming language version 1.5 book - Part 9 of 31
The Ring programming language version 1.5 book - Part 9 of 31
Mahmoud Samir Fayed
 
F# in the real world (NDC)
F# in the real world (NDC)F# in the real world (NDC)
F# in the real world (NDC)
Yan Cui
 
The main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdfThe main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdf
asif1401
 
Parallel Futures of a Game Engine
Parallel Futures of a Game EngineParallel Futures of a Game Engine
Parallel Futures of a Game Engine
Johan Andersson
 
Modular games in Unity / Paweł Krakowiak (Rage Quit Games)
Modular games in Unity / Paweł Krakowiak (Rage Quit Games)Modular games in Unity / Paweł Krakowiak (Rage Quit Games)
Modular games in Unity / Paweł Krakowiak (Rage Quit Games)
DevGAMM Conference
 
package com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdfpackage com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdf
info430661
 
Games, AI, and Research - Part 2 Training (FightingICE AI Programming)
Games, AI, and Research - Part 2 Training (FightingICE AI Programming)Games, AI, and Research - Part 2 Training (FightingICE AI Programming)
Games, AI, and Research - Part 2 Training (FightingICE AI Programming)
Pujana Paliyawan
 
WordPress Café November - Sport Leaderboards with a Plugin
WordPress Café November - Sport Leaderboards with a PluginWordPress Café November - Sport Leaderboards with a Plugin
WordPress Café November - Sport Leaderboards with a Plugin
Exove
 
You will write a multi-interface version of the well-known concentra.pdf
You will write a multi-interface version of the well-known concentra.pdfYou will write a multi-interface version of the well-known concentra.pdf
You will write a multi-interface version of the well-known concentra.pdf
FashionColZone
 
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdfIfgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
fazilfootsteps
 
Tic tac toe
Tic tac toeTic tac toe
Tic tac toe
KrishanKantGupta5
 
Tips and Tricks for Avoiding Common Query Pitfalls Christian Kurze
Tips and Tricks for Avoiding Common Query Pitfalls Christian KurzeTips and Tricks for Avoiding Common Query Pitfalls Christian Kurze
Tips and Tricks for Avoiding Common Query Pitfalls Christian Kurze
MongoDB
 
Tic tac toe on c++ project
Tic tac toe on c++ projectTic tac toe on c++ project
Tic tac toe on c++ project
Utkarsh Aggarwal
 
The Ring programming language version 1.8 book - Part 76 of 202
The Ring programming language version 1.8 book - Part 76 of 202The Ring programming language version 1.8 book - Part 76 of 202
The Ring programming language version 1.8 book - Part 76 of 202
Mahmoud Samir Fayed
 
MongoDB World 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB World 2018: Tips and Tricks for Avoiding Common Query PitfallsMongoDB World 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB World 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB
 
Bowling Game Kata in C# Adapted
Bowling Game Kata in C# AdaptedBowling Game Kata in C# Adapted
Bowling Game Kata in C# AdaptedMike Clement
 
MongoDB.local Austin 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB.local Austin 2018: Tips and Tricks for Avoiding Common Query PitfallsMongoDB.local Austin 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB.local Austin 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB
 
The Ring programming language version 1.7 book - Part 74 of 196
The Ring programming language version 1.7 book - Part 74 of 196The Ring programming language version 1.7 book - Part 74 of 196
The Ring programming language version 1.7 book - Part 74 of 196
Mahmoud Samir Fayed
 
Please help with this. program must be written in C# .. All of the g.pdf
Please help with this. program must be written in C# .. All of the g.pdfPlease help with this. program must be written in C# .. All of the g.pdf
Please help with this. program must be written in C# .. All of the g.pdf
manjan6
 

Similar to New Tools for a More Functional C++ (20)

C++You will design a program to play a simplified version of war, .pdf
C++You will design a program to play a simplified version of war, .pdfC++You will design a program to play a simplified version of war, .pdf
C++You will design a program to play a simplified version of war, .pdf
 
The Ring programming language version 1.5 book - Part 9 of 31
The Ring programming language version 1.5 book - Part 9 of 31The Ring programming language version 1.5 book - Part 9 of 31
The Ring programming language version 1.5 book - Part 9 of 31
 
F# in the real world (NDC)
F# in the real world (NDC)F# in the real world (NDC)
F# in the real world (NDC)
 
The main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdfThe main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdf
 
Parallel Futures of a Game Engine
Parallel Futures of a Game EngineParallel Futures of a Game Engine
Parallel Futures of a Game Engine
 
Modular games in Unity / Paweł Krakowiak (Rage Quit Games)
Modular games in Unity / Paweł Krakowiak (Rage Quit Games)Modular games in Unity / Paweł Krakowiak (Rage Quit Games)
Modular games in Unity / Paweł Krakowiak (Rage Quit Games)
 
package com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdfpackage com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdf
 
Games, AI, and Research - Part 2 Training (FightingICE AI Programming)
Games, AI, and Research - Part 2 Training (FightingICE AI Programming)Games, AI, and Research - Part 2 Training (FightingICE AI Programming)
Games, AI, and Research - Part 2 Training (FightingICE AI Programming)
 
WordPress Café November - Sport Leaderboards with a Plugin
WordPress Café November - Sport Leaderboards with a PluginWordPress Café November - Sport Leaderboards with a Plugin
WordPress Café November - Sport Leaderboards with a Plugin
 
You will write a multi-interface version of the well-known concentra.pdf
You will write a multi-interface version of the well-known concentra.pdfYou will write a multi-interface version of the well-known concentra.pdf
You will write a multi-interface version of the well-known concentra.pdf
 
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdfIfgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
 
Tic tac toe
Tic tac toeTic tac toe
Tic tac toe
 
Tips and Tricks for Avoiding Common Query Pitfalls Christian Kurze
Tips and Tricks for Avoiding Common Query Pitfalls Christian KurzeTips and Tricks for Avoiding Common Query Pitfalls Christian Kurze
Tips and Tricks for Avoiding Common Query Pitfalls Christian Kurze
 
Tic tac toe on c++ project
Tic tac toe on c++ projectTic tac toe on c++ project
Tic tac toe on c++ project
 
The Ring programming language version 1.8 book - Part 76 of 202
The Ring programming language version 1.8 book - Part 76 of 202The Ring programming language version 1.8 book - Part 76 of 202
The Ring programming language version 1.8 book - Part 76 of 202
 
MongoDB World 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB World 2018: Tips and Tricks for Avoiding Common Query PitfallsMongoDB World 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB World 2018: Tips and Tricks for Avoiding Common Query Pitfalls
 
Bowling Game Kata in C# Adapted
Bowling Game Kata in C# AdaptedBowling Game Kata in C# Adapted
Bowling Game Kata in C# Adapted
 
MongoDB.local Austin 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB.local Austin 2018: Tips and Tricks for Avoiding Common Query PitfallsMongoDB.local Austin 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB.local Austin 2018: Tips and Tricks for Avoiding Common Query Pitfalls
 
The Ring programming language version 1.7 book - Part 74 of 196
The Ring programming language version 1.7 book - Part 74 of 196The Ring programming language version 1.7 book - Part 74 of 196
The Ring programming language version 1.7 book - Part 74 of 196
 
Please help with this. program must be written in C# .. All of the g.pdf
Please help with this. program must be written in C# .. All of the g.pdfPlease help with this. program must be written in C# .. All of the g.pdf
Please help with this. program must be written in C# .. All of the g.pdf
 

More from Sumant Tambe

Kafka tiered-storage-meetup-2022-final-presented
Kafka tiered-storage-meetup-2022-final-presentedKafka tiered-storage-meetup-2022-final-presented
Kafka tiered-storage-meetup-2022-final-presented
Sumant Tambe
 
Systematic Generation Data and Types in C++
Systematic Generation Data and Types in C++Systematic Generation Data and Types in C++
Systematic Generation Data and Types in C++
Sumant Tambe
 
Tuning kafka pipelines
Tuning kafka pipelinesTuning kafka pipelines
Tuning kafka pipelines
Sumant Tambe
 
C++ Coroutines
C++ CoroutinesC++ Coroutines
C++ Coroutines
Sumant Tambe
 
C++ Generators and Property-based Testing
C++ Generators and Property-based TestingC++ Generators and Property-based Testing
C++ Generators and Property-based Testing
Sumant Tambe
 
Reactive Stream Processing in Industrial IoT using DDS and Rx
Reactive Stream Processing in Industrial IoT using DDS and RxReactive Stream Processing in Industrial IoT using DDS and Rx
Reactive Stream Processing in Industrial IoT using DDS and Rx
Sumant Tambe
 
RPC over DDS Beta 1
RPC over DDS Beta 1RPC over DDS Beta 1
RPC over DDS Beta 1
Sumant Tambe
 
Remote Log Analytics Using DDS, ELK, and RxJS
Remote Log Analytics Using DDS, ELK, and RxJSRemote Log Analytics Using DDS, ELK, and RxJS
Remote Log Analytics Using DDS, ELK, and RxJS
Sumant Tambe
 
Property-based Testing and Generators (Lua)
Property-based Testing and Generators (Lua)Property-based Testing and Generators (Lua)
Property-based Testing and Generators (Lua)
Sumant Tambe
 
Reactive Stream Processing for Data-centric Publish/Subscribe
Reactive Stream Processing for Data-centric Publish/SubscribeReactive Stream Processing for Data-centric Publish/Subscribe
Reactive Stream Processing for Data-centric Publish/Subscribe
Sumant Tambe
 
Reactive Stream Processing Using DDS and Rx
Reactive Stream Processing Using DDS and RxReactive Stream Processing Using DDS and Rx
Reactive Stream Processing Using DDS and Rx
Sumant Tambe
 
Fun with Lambdas: C++14 Style (part 2)
Fun with Lambdas: C++14 Style (part 2)Fun with Lambdas: C++14 Style (part 2)
Fun with Lambdas: C++14 Style (part 2)
Sumant Tambe
 
Fun with Lambdas: C++14 Style (part 1)
Fun with Lambdas: C++14 Style (part 1)Fun with Lambdas: C++14 Style (part 1)
Fun with Lambdas: C++14 Style (part 1)
Sumant Tambe
 
An Extensible Architecture for Avionics Sensor Health Assessment Using DDS
An Extensible Architecture for Avionics Sensor Health Assessment Using DDSAn Extensible Architecture for Avionics Sensor Health Assessment Using DDS
An Extensible Architecture for Avionics Sensor Health Assessment Using DDS
Sumant Tambe
 
Overloading in Overdrive: A Generic Data-Centric Messaging Library for DDS
Overloading in Overdrive: A Generic Data-Centric Messaging Library for DDSOverloading in Overdrive: A Generic Data-Centric Messaging Library for DDS
Overloading in Overdrive: A Generic Data-Centric Messaging Library for DDS
Sumant Tambe
 
Standardizing the Data Distribution Service (DDS) API for Modern C++
Standardizing the Data Distribution Service (DDS) API for Modern C++Standardizing the Data Distribution Service (DDS) API for Modern C++
Standardizing the Data Distribution Service (DDS) API for Modern C++Sumant Tambe
 
Communication Patterns Using Data-Centric Publish/Subscribe
Communication Patterns Using Data-Centric Publish/SubscribeCommunication Patterns Using Data-Centric Publish/Subscribe
Communication Patterns Using Data-Centric Publish/Subscribe
Sumant Tambe
 
C++11 Idioms @ Silicon Valley Code Camp 2012
C++11 Idioms @ Silicon Valley Code Camp 2012 C++11 Idioms @ Silicon Valley Code Camp 2012
C++11 Idioms @ Silicon Valley Code Camp 2012
Sumant Tambe
 
Retargeting Embedded Software Stack for Many-Core Systems
Retargeting Embedded Software Stack for Many-Core SystemsRetargeting Embedded Software Stack for Many-Core Systems
Retargeting Embedded Software Stack for Many-Core Systems
Sumant Tambe
 
Ph.D. Dissertation
Ph.D. DissertationPh.D. Dissertation
Ph.D. Dissertation
Sumant Tambe
 

More from Sumant Tambe (20)

Kafka tiered-storage-meetup-2022-final-presented
Kafka tiered-storage-meetup-2022-final-presentedKafka tiered-storage-meetup-2022-final-presented
Kafka tiered-storage-meetup-2022-final-presented
 
Systematic Generation Data and Types in C++
Systematic Generation Data and Types in C++Systematic Generation Data and Types in C++
Systematic Generation Data and Types in C++
 
Tuning kafka pipelines
Tuning kafka pipelinesTuning kafka pipelines
Tuning kafka pipelines
 
C++ Coroutines
C++ CoroutinesC++ Coroutines
C++ Coroutines
 
C++ Generators and Property-based Testing
C++ Generators and Property-based TestingC++ Generators and Property-based Testing
C++ Generators and Property-based Testing
 
Reactive Stream Processing in Industrial IoT using DDS and Rx
Reactive Stream Processing in Industrial IoT using DDS and RxReactive Stream Processing in Industrial IoT using DDS and Rx
Reactive Stream Processing in Industrial IoT using DDS and Rx
 
RPC over DDS Beta 1
RPC over DDS Beta 1RPC over DDS Beta 1
RPC over DDS Beta 1
 
Remote Log Analytics Using DDS, ELK, and RxJS
Remote Log Analytics Using DDS, ELK, and RxJSRemote Log Analytics Using DDS, ELK, and RxJS
Remote Log Analytics Using DDS, ELK, and RxJS
 
Property-based Testing and Generators (Lua)
Property-based Testing and Generators (Lua)Property-based Testing and Generators (Lua)
Property-based Testing and Generators (Lua)
 
Reactive Stream Processing for Data-centric Publish/Subscribe
Reactive Stream Processing for Data-centric Publish/SubscribeReactive Stream Processing for Data-centric Publish/Subscribe
Reactive Stream Processing for Data-centric Publish/Subscribe
 
Reactive Stream Processing Using DDS and Rx
Reactive Stream Processing Using DDS and RxReactive Stream Processing Using DDS and Rx
Reactive Stream Processing Using DDS and Rx
 
Fun with Lambdas: C++14 Style (part 2)
Fun with Lambdas: C++14 Style (part 2)Fun with Lambdas: C++14 Style (part 2)
Fun with Lambdas: C++14 Style (part 2)
 
Fun with Lambdas: C++14 Style (part 1)
Fun with Lambdas: C++14 Style (part 1)Fun with Lambdas: C++14 Style (part 1)
Fun with Lambdas: C++14 Style (part 1)
 
An Extensible Architecture for Avionics Sensor Health Assessment Using DDS
An Extensible Architecture for Avionics Sensor Health Assessment Using DDSAn Extensible Architecture for Avionics Sensor Health Assessment Using DDS
An Extensible Architecture for Avionics Sensor Health Assessment Using DDS
 
Overloading in Overdrive: A Generic Data-Centric Messaging Library for DDS
Overloading in Overdrive: A Generic Data-Centric Messaging Library for DDSOverloading in Overdrive: A Generic Data-Centric Messaging Library for DDS
Overloading in Overdrive: A Generic Data-Centric Messaging Library for DDS
 
Standardizing the Data Distribution Service (DDS) API for Modern C++
Standardizing the Data Distribution Service (DDS) API for Modern C++Standardizing the Data Distribution Service (DDS) API for Modern C++
Standardizing the Data Distribution Service (DDS) API for Modern C++
 
Communication Patterns Using Data-Centric Publish/Subscribe
Communication Patterns Using Data-Centric Publish/SubscribeCommunication Patterns Using Data-Centric Publish/Subscribe
Communication Patterns Using Data-Centric Publish/Subscribe
 
C++11 Idioms @ Silicon Valley Code Camp 2012
C++11 Idioms @ Silicon Valley Code Camp 2012 C++11 Idioms @ Silicon Valley Code Camp 2012
C++11 Idioms @ Silicon Valley Code Camp 2012
 
Retargeting Embedded Software Stack for Many-Core Systems
Retargeting Embedded Software Stack for Many-Core SystemsRetargeting Embedded Software Stack for Many-Core Systems
Retargeting Embedded Software Stack for Many-Core Systems
 
Ph.D. Dissertation
Ph.D. DissertationPh.D. Dissertation
Ph.D. Dissertation
 

Recently uploaded

How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
Cyanic lab
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
takuyayamamoto1800
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
informapgpstrackings
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Anthony Dahanne
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
Globus
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
Globus
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
IES VE
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
Matt Welsh
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
Globus
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
WSO2
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
XfilesPro
 
RISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent EnterpriseRISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent Enterprise
Srikant77
 

Recently uploaded (20)

How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
 
RISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent EnterpriseRISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent Enterprise
 

New Tools for a More Functional C++

  • 1. New Tools for a More Functional C++ Sumant Tambe Sr. Software Engineer, LinkedIn Microsoft MVP SF Bay Area ACCU Sept 28, 2017
  • 2. Blogger (since 2005) Coditation—Elegant Code for Big Data Author (wikibook) Open-source contributor Since 2013 (Visual Studio and Dev Tech)
  • 3. Functional Programming in C++ by Ivan Cukic (ETA early 2018) Reviewer
  • 4. Sum Types and (pseudo) Pattern Matching
  • 5. Modeling Alternatives Inheritance vs std::variant • States of a game of Tennis • NormalScore • DeuceScore • AdvantageScore • GameCompleteScore
  • 6. Modeling game states using std::variant struct NormalScore { Player p1, p2; int p1_score, p2_score; }; struct DeuceScore { Player p1, p2; }; struct AdvantageScore { Player lead, lagging; }; struct GameCompleteScore { Player winner, loser; int loser_score; }; using GameState = std::variant<NormalScore, DeuceScore, AdvantageScore, GameCompleteScore>;
  • 7. Print GameState (std::variant) struct GameStatePrinter { std::ostream &o; explicit GameStatePrinter(std::ostream& out) : o(out) {} void operator ()(const NormalScore& ns) const { o << "NormalScore[" << ns.p1 << ns.p2 << ns.p1_score << ns.p2_score << "]"; } void operator ()(const DeuceScore& ds) const { o << "DeuceScore[" << ds.p1 << "," << ds.p2 << "]"; } void operator ()(const AdvantageScore& as) const { o << "AdvantageScore[" << as.lead << "," << as.lagging << "]"; } void operator ()(const GameCompleteScore& gc) const { o << "GameComplete[" << gc.winner << gc.loser << gc.loser_score << "]"; } }; std::ostream & operator << (std::ostream& o, const GameState& game) { std::visit(GameStatePrinter(o), game); return o; }
  • 8. std::visit spews blood when you miss a case
  • 9. Print GameState. Fancier! std::ostream & operator << (std::ostream& o, const GameState& game) { std::visit(overloaded { [&](const NormalScore& ns) { o << "NormalScore" << ns.p1 << ns.p2 << ns.p1_score << ns.p2_score; }, [&](const DeuceScore& gc) { o << "DeuceScore[" << ds.p1 << "," << ds.p2 << "]"; }, [&](const AdvantageScore& as) { o << "AdvantageScore[" << as.lead << "," << as.lagging << "]"; }, [&](const GameCompleteScore& gc) { o << "GameComplete[" << gc.winner << gc.loser << gc.loser_score << "]"; } }, game); return o; }
  • 10. Passing Two Variants to std::visit std::ostream & operator << (std::ostream& o, const GameState& game) { std::visit(overloaded { [&](const NormalScore& ns, const auto& other) { o << "NormalScore" << ns.p1 << ns.p2 << ns.p1_score << ns.p2_score; }, [&](const DeuceScore& gc, const auto& other) { o << "DeuceScore[" << ds.p1 << "," << ds.p2 << "]"; }, [&](const AdvantageScore& as, const auto& other) { o << "AdvantageScore[" << as.lead << "," << as.lagging << "]"; }, [&](const GameCompleteScore& gc, const auto& other) { o << "GameComplete[" << gc.winner << gc.loser << gc.loser_score << "]"; } }, game, someother_variant); return o; } There can be arbitrary number of arbitrary variant types. The visitor must cover all cases
  • 11. A Template to Inherit Lambdas template <class... Ts> struct overloaded : Ts... { using Ts::operator()...; explicit overloaded(Ts... ts) : Ts(ts)... {} }; A User-Defined Deduction Guide explicit overloaded(Ts... ts) : Ts(ts)... {} template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
  • 12. Next GameState Algorithm (all cases in one place) GameState next (const GameState& now, const Player& who_scored) { return std::visit(overloaded { [&](const DeuceScore& ds) -> GameState { if (ds.p1 == who_scored) return AdvantageScore{ds.p1, ds.p2}; else return AdvantageScore{ds.p2, ds.p1}; }, [&](const AdvantageScore& as) -> GameState { if (as.lead == who_scored) return GameCompleteScore{as.lead, as.lagging, 40}; else return DeuceScore{as.lead, as.lagging}; }, [&](const GameCompleteScore &) -> GameState { throw "Illegal State"; }, [&](const NormalScore& ns) -> GameState { if (ns.p1 == who_scored) { switch (ns.p1_score) { case 0: return NormalScore{ns.p1, ns.p2, 15, ns.p2_score}; case 15: return NormalScore{ns.p1, ns.p2, 30, ns.p2_score}; case 30: if (ns.p2_score < 40) return NormalScore{ns.p1, ns.p2, 40, ns.p2_score}; else return DeuceScore{ns.p1, ns.p2}; case 40: return GameCompleteScore{ns.p1, ns.p2, ns.p2_score}; default: throw "Makes no sense!"; } } else { switch (ns.p2_score) { case 0: return NormalScore{ns.p1, ns.p2, ns.p1_score, 15}; case 15: return NormalScore{ns.p1, ns.p2, ns.p1_score, 30}; case 30: if (ns.p1_score < 40) return NormalScore{ns.p1, ns.p2, ns.p1_score, 40}; else return DeuceScore{ns.p1, ns.p2}; case 40: return GameCompleteScore{ns.p2, ns.p1, ns.p1_score}; default: throw "Makes no sense!"; } } } }, now); }
  • 13. Modeling Alternatives with Inheritance class GameState { std::unique_ptr<GameStateImpl> _state; public: void next(const Player& who_scored) {} }; class GameStateImpl { Player p1, p2; public: virtual GameStateImpl * next( const Player& who_scored) = 0; virtual ~GameStateImpl(){} }; class NormalScore : public GameStateImpl { int p1_score, p2_score; public: GameStateImpl * next(const Player&); }; class DeuceScore : public GameStateImpl { public: GameStateImpl * next(const Player&); }; class AdvantageScore : public GameStateImpl { int lead; public: GameStateImpl * next(const Player&); }; class GameCompleteScore :public GameStateImpl{ int winner, loser_score; public: GameStateImpl * next(const Player&); };
  • 14. Sharing State is easier with Inheritance class GameState { std::unique_ptr<GameStateImpl> _state; public: void next(const Player& who_scored) {} Player& who_is_serving() const; double fastest_serve_speed() const; GameState get_last_state() const; }; class GameStateImpl { Player p1, p2; int serving_player; double speed; GameState last_state; public: virtual GameStateImpl * next( const Player& who_scored) = 0; virtual Player& who_is_serving() const; virtual double fastest_serve_speed() const; virtual GameState get_last_state() const; };
  • 15. Sharing Common State is Repetitive with std::variant Player who_is_serving = std::visit([](auto& s) { return s.who_is_serving(); }, state); Player who_is_serving = state.who_is_serving(); ceremony! struct NormalScore { Player p1, p2; int p1_score, p2_score; int serving_player; Player & who_is_serving(); }; struct DeuceScore { Player p1, p2; int serving_player; Player & who_is_serving(); }; struct AdvantageScore { Player lead, lagging; int serving_player; Player & who_is_serving(); }; struct GameCompleteScore { Player winner, loser; int loser_score; int serving_player; Player & who_is_serving(); };
  • 16. How about recursive std::variant? struct NormalScore { Player p1, p2; int p1_score, p2_score; int serving_player; Player & who_is_serving(); GameState last_state; }; struct DeuceScore { Player p1, p2; int serving_player; Player & who_is_serving(); GameState last_state; }; struct AdvantageScore { Player lead, lagging; int serving_player; Player & who_is_serving(); GameState last_state; }; struct GameCompleteScore { Player winner, loser; int loser_score; int serving_player; Player & who_is_serving(); GameState last_state; }; Not possible unless you use recursive_wrapper and dynamic allocation. Not in C++17. Dare I say, it’s not algebraic? It does not compose  std::variant is a container. Not an abstraction.
  • 17. std::variant disables fluent interfaces { using GameState = std::variant<NormalScore, DeuceScore, AdvantageScore, GameCompleteScore>; GameState state = NormalScore {..}; GameState last_state = std::visit([](auto& s) { return s.get_last_state(); }, state); double last_speed = std::visit([](auto& s) { return state.fastest_serve_speed(); }, last_state); double last_speed = state.get_last_state().fastest_serve_speed(); } ceremony!
  • 18. Combine Implementation Inheritance with std::variant { using GameState = std::variant<NormalScore_v2, DeuceScore_v2, AdvantageScore_v2, GameCompleteScore_v2>; GameState state = NormalScore_v2 {..}; Player who_is_serving = std::visit([](SharedGameState& s) { return s.who_is_serving(); }, state); Player who_is_serving = state.who_is_serving(); } SharedGameState who_is_serving() NormalScore_v2 DeuceScore_v2 AdvantageScore_v2 GameCompleteScore_v2 ceremony!
  • 19. Modeling Alternatives Inheritance std::variant Dynamic Allocation No dynamic allocation Intrusive Non-intrusive Reference semantics (how will you copy a vector?) Value semantics Algorithm scattered into classes Algorithm in one place Language supported Clear errors if pure-virtual is not implemented Library supported std::visit spews blood on missing cases Creates a first-class abstraction It’s just a container Keeps fluent interfaces Disables fluent interfaces. Repeated std::visit Supports recursive types (Composite) Must use recursive_wrapper and dynamic allocation. Not in the C++17 standard.
  • 21. const is shallow struct X { void bar(); }; struct Y { X* xptr; explicit Y(X* x) : xptr(x) {} void foo() const { xptr->bar(); } }; { const Y y(new X); y.foo(); // mutates X?? }
  • 22. Deep Immutability: propagate_const<T> struct X { void bar(); void bar() const; // Compiler error without this function }; struct Y { X* xptr; propagate_const<X *> xptr; explicit Y(X* x) : xptr(x) {} void foo() const { xptr->bar(); } }; { const Y y(new X); y.foo(); // calls X.bar() const }
  • 23. Deep Immutability: propagate_const<T> #include <experimental/propagate_const> using std::experimental::propagate_const; { propagate_const<X *> xptr; propagate_const<std::unique_ptr<X>> uptr; propagate_const<std::shared_ptr<X>> shptr; const propagate_const<std::shared_ptr<X>> c_shptr; shptr.get() === X* c_shptr.get() === const X* *shptr === X& *c_shptr === const X& get_underlying(shptr) === shared_ptr<X> get_underlying(c_shptr) === const shared_ptr<X> shptr = another_shptr; // Error. Not copy-assignable shptr = std::move(another_shptr) // but movable Library fundamental TS v2
  • 25. The Named Parameter Idiom (mutable) class configs { std::string server; std::string protocol; public: configs & set_server(const std::string& s); configs & set_protocol(const std::string& s); }; start_server(configs().set_server(“localhost”) .set_protocol(“https”));
  • 26. The Named Parameter Idiom (immutable) class configs { public: configs set_server(const std::string& s) const { configs temp(*this); temp.server = s; return temp; } configs set_protocol(const std::string& proto) const { configs temp(*this); temp.protocol = proto; return temp; } }; start_server(configs().set_server(“localhost”) .set_protocol(“https”)); Avoid copy-constructors?
  • 27. The Named Parameter Idiom (immutable*) class configs { public: configs set_server(const std::string& s) const { configs temp(*this); temp.server = s; return temp; } configs set_protocol(const std::string& proto) const { configs temp(*this); temp.protocol = proto; return temp; } configs set_server(const std::string& s) && { server = s; return *this; } configs set_protocol(const std::string& proto) && { protocol = proto; return *this; } }; start_server(configs().set_server(“localhost”) .set_protocol(“https”)); & &
  • 28. The Named Parameter Idiom (immutable*) class configs { public: configs set_server(const std::string& s) const { configs temp(*this); temp.server = s; return temp; } configs set_protocol(const std::string& proto) const { configs temp(*this); temp.protocol = proto; return temp; } configs&& set_server(const std::string& s) && { server = s; return *this; std::move(*this); } configs&& set_protocol(const std::string& proto) && { protocol = proto; return *this; std::move(*this); } }; start_server(configs().set_server(“localhost”) .set_protocol(“https”)); & &

Editor's Notes

  1. How many of you think that it’s an important benefit that all cases are together.
  2. Who_is_serving visitor.
  3. Who_is_serving visitor.
  4. Who_is_serving visitor.
  5. *this is an lvalue. Still calls the copy-constructor.