SlideShare una empresa de Scribd logo
1 de 29
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!

Más contenido relacionado

La actualidad más candente

API Asynchrones en Java 8
API Asynchrones en Java 8API Asynchrones en Java 8
API Asynchrones en Java 8José Paumard
 
Intégration continue
Intégration continueIntégration continue
Intégration continueKlee Group
 
Diving into SWUpdate: adding new platform support in 30minutes with Yocto/OE !
Diving into SWUpdate: adding new platform support in 30minutes with Yocto/OE !Diving into SWUpdate: adding new platform support in 30minutes with Yocto/OE !
Diving into SWUpdate: adding new platform support in 30minutes with Yocto/OE !Pierre-jean Texier
 
Cours java avance débutant facile l'essentiel swing ,events
Cours java avance débutant facile l'essentiel swing ,events Cours java avance débutant facile l'essentiel swing ,events
Cours java avance débutant facile l'essentiel swing ,events Houssem Hamrouni
 
Linux kernel debugging
Linux kernel debuggingLinux kernel debugging
Linux kernel debugginglibfetion
 
Présentation de ECMAScript 6
Présentation de ECMAScript 6Présentation de ECMAScript 6
Présentation de ECMAScript 6Julien CROUZET
 
Ansible Introduction
Ansible Introduction Ansible Introduction
Ansible Introduction Robert Reiz
 
Intégration continue et déploiement continue avec Jenkins
Intégration continue et déploiement continue avec JenkinsIntégration continue et déploiement continue avec Jenkins
Intégration continue et déploiement continue avec JenkinsKokou Gaglo
 
Kernel Recipes 2017 - An introduction to the Linux DRM subsystem - Maxime Ripard
Kernel Recipes 2017 - An introduction to the Linux DRM subsystem - Maxime RipardKernel Recipes 2017 - An introduction to the Linux DRM subsystem - Maxime Ripard
Kernel Recipes 2017 - An introduction to the Linux DRM subsystem - Maxime RipardAnne Nicolas
 
Introduction à l’intégration continue avec Jenkins
Introduction à l’intégration continue avec JenkinsIntroduction à l’intégration continue avec Jenkins
Introduction à l’intégration continue avec JenkinsEric Hogue
 
News And Development Update Of The CloudStack Tungsten Fabric SDN Plug-in
News And Development Update Of The CloudStack Tungsten Fabric SDN Plug-inNews And Development Update Of The CloudStack Tungsten Fabric SDN Plug-in
News And Development Update Of The CloudStack Tungsten Fabric SDN Plug-inShapeBlue
 
Formation libre OpenStack en Français
Formation libre OpenStack en FrançaisFormation libre OpenStack en Français
Formation libre OpenStack en FrançaisOsones
 
Sécurité asterisk web
Sécurité asterisk webSécurité asterisk web
Sécurité asterisk webAgarik
 
Introduction to Jhipster
Introduction to JhipsterIntroduction to Jhipster
Introduction to JhipsterKnoldus Inc.
 

La actualidad más candente (20)

API Asynchrones en Java 8
API Asynchrones en Java 8API Asynchrones en Java 8
API Asynchrones en Java 8
 
Intégration continue
Intégration continueIntégration continue
Intégration continue
 
Diving into SWUpdate: adding new platform support in 30minutes with Yocto/OE !
Diving into SWUpdate: adding new platform support in 30minutes with Yocto/OE !Diving into SWUpdate: adding new platform support in 30minutes with Yocto/OE !
Diving into SWUpdate: adding new platform support in 30minutes with Yocto/OE !
 
Cours java avance débutant facile l'essentiel swing ,events
Cours java avance débutant facile l'essentiel swing ,events Cours java avance débutant facile l'essentiel swing ,events
Cours java avance débutant facile l'essentiel swing ,events
 
Linux DMA Engine
Linux DMA EngineLinux DMA Engine
Linux DMA Engine
 
Linux kernel debugging
Linux kernel debuggingLinux kernel debugging
Linux kernel debugging
 
Présentation de ECMAScript 6
Présentation de ECMAScript 6Présentation de ECMAScript 6
Présentation de ECMAScript 6
 
Ansible Introduction
Ansible Introduction Ansible Introduction
Ansible Introduction
 
淺談探索 Linux 系統設計之道
淺談探索 Linux 系統設計之道 淺談探索 Linux 系統設計之道
淺談探索 Linux 系統設計之道
 
I2C Drivers
I2C DriversI2C Drivers
I2C Drivers
 
Intégration continue et déploiement continue avec Jenkins
Intégration continue et déploiement continue avec JenkinsIntégration continue et déploiement continue avec Jenkins
Intégration continue et déploiement continue avec Jenkins
 
Kernel Recipes 2017 - An introduction to the Linux DRM subsystem - Maxime Ripard
Kernel Recipes 2017 - An introduction to the Linux DRM subsystem - Maxime RipardKernel Recipes 2017 - An introduction to the Linux DRM subsystem - Maxime Ripard
Kernel Recipes 2017 - An introduction to the Linux DRM subsystem - Maxime Ripard
 
Introduction à l’intégration continue avec Jenkins
Introduction à l’intégration continue avec JenkinsIntroduction à l’intégration continue avec Jenkins
Introduction à l’intégration continue avec Jenkins
 
Les attaques MITM
Les attaques MITMLes attaques MITM
Les attaques MITM
 
Introduction to Linux Drivers
Introduction to Linux DriversIntroduction to Linux Drivers
Introduction to Linux Drivers
 
Character Drivers
Character DriversCharacter Drivers
Character Drivers
 
News And Development Update Of The CloudStack Tungsten Fabric SDN Plug-in
News And Development Update Of The CloudStack Tungsten Fabric SDN Plug-inNews And Development Update Of The CloudStack Tungsten Fabric SDN Plug-in
News And Development Update Of The CloudStack Tungsten Fabric SDN Plug-in
 
Formation libre OpenStack en Français
Formation libre OpenStack en FrançaisFormation libre OpenStack en Français
Formation libre OpenStack en Français
 
Sécurité asterisk web
Sécurité asterisk webSécurité asterisk web
Sécurité asterisk web
 
Introduction to Jhipster
Introduction to JhipsterIntroduction to Jhipster
Introduction to Jhipster
 

Similar a New Tools for a More Functional C++

Game programming-help
Game programming-helpGame programming-help
Game programming-helpSteve Nash
 
public interface Game Note interface in place of class { .pdf
public interface Game  Note interface in place of class { .pdfpublic interface Game  Note interface in place of class { .pdf
public interface Game Note interface in place of class { .pdfkavithaarp
 
David Kopal - Write better React with ReasonML - Codemotion Milan 2018
David Kopal - Write better React with ReasonML - Codemotion Milan 2018David Kopal - Write better React with ReasonML - Codemotion Milan 2018
David Kopal - Write better React with ReasonML - Codemotion Milan 2018Codemotion
 
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, .pdfezzi97
 
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 31Mahmoud 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 {.pdfasif1401
 
Parallel Futures of a Game Engine
Parallel Futures of a Game EngineParallel Futures of a Game Engine
Parallel Futures of a Game EngineJohan 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() {.pdfinfo430661
 
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 PluginExove
 
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.pdfFashionColZone
 
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.pdffazilfootsteps
 
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 KurzeMongoDB
 
Tic tac toe on c++ project
Tic tac toe on c++ projectTic tac toe on c++ project
Tic tac toe on c++ projectUtkarsh 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 202Mahmoud 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 PitfallsMongoDB
 
Bowling Game Kata in C# Adapted
Bowling Game Kata in C# AdaptedBowling Game Kata in C# Adapted
Bowling Game Kata in C# AdaptedMike Clement
 

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

Game programming-help
Game programming-helpGame programming-help
Game programming-help
 
public interface Game Note interface in place of class { .pdf
public interface Game  Note interface in place of class { .pdfpublic interface Game  Note interface in place of class { .pdf
public interface Game Note interface in place of class { .pdf
 
David Kopal - Write better React with ReasonML - Codemotion Milan 2018
David Kopal - Write better React with ReasonML - Codemotion Milan 2018David Kopal - Write better React with ReasonML - Codemotion Milan 2018
David Kopal - Write better React with ReasonML - Codemotion Milan 2018
 
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
 

Más de 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-presentedSumant 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 pipelinesSumant Tambe
 
C++ Generators and Property-based Testing
C++ Generators and Property-based TestingC++ Generators and Property-based Testing
C++ Generators and Property-based TestingSumant 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 RxSumant Tambe
 
RPC over DDS Beta 1
RPC over DDS Beta 1RPC over DDS Beta 1
RPC over DDS Beta 1Sumant 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 RxJSSumant 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/SubscribeSumant 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 RxSumant 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 DDSSumant 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 DDSSumant 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/SubscribeSumant 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 SystemsSumant Tambe
 
Ph.D. Dissertation
Ph.D. DissertationPh.D. Dissertation
Ph.D. DissertationSumant Tambe
 

Más de 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
 

Último

Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfDrew Moseley
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
cpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptcpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptrcbcrtm
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsChristian Birchler
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 

Último (20)

Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Odoo Development Company in India | Devintelle Consulting Service
Odoo Development Company in India | Devintelle Consulting ServiceOdoo Development Company in India | Devintelle Consulting Service
Odoo Development Company in India | Devintelle Consulting Service
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdf
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
cpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptcpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.ppt
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 

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”)); & &

Notas del editor

  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.