SlideShare a Scribd company logo
BRK2146
 What’s new?
 “Classic” vs. “Modern” C++
 Move semantics; vocabulary types
 “Top two” general issues/techniques
 RAII + scopes
 Error handling
 “One more”
 Pointers: Dumb and smart (and smart used correctly)
 “What should every C++ programmer be
expected to know?”
 For years, there has not been a single source to
point to.
 Now there is. Readable on a long plane flight.
 Recommend it heavily!
 Also a demonstration that modern C++ is simpler to
teach and explain.
 Currently being updated for C++17,
Second Edition ETA July 2018.
Then: C++98 code
circle* p = new circle( 42 );
vector<shape*> v = load_shapes();
for( vector<shape*>::iterator i=v.begin(); i!=v.end(); ++i ){
if( *i && **i == *p )
cout << **i << “ is a matchn”;
}
// … later, possibly elsewhere …
for( vector<shape*>::iterator i = v.begin();
i != v.end(); ++i ) {
delete *i;
}
delete p;
Then: C++98 code Now: Modern C++
circle* p = new circle( 42 );
vector<shape*> v = load_shapes();
for( vector<shape*>::iterator i=v.begin(); i!=v.end(); ++i ){
if( *i && **i == *p )
cout << **i << “ is a matchn”;
}
// … later, possibly elsewhere …
for( vector<shape*>::iterator i = v.begin();
i != v.end(); ++i ) {
delete *i;
}
delete p;
auto p = make_shared<circle>( 42 );
auto v = load_shapes();
for( auto& s : v ) {
if( s && *s == *p )
cout << *s << “ is a matchn”;
}
T*  shared_ptr<T>
new  make_unique
or make_shared
no need for “delete” –
automatic lifetime management
exception-safe
range-for
auto type deduction
not exception-safe
missing try/catch,
__try/__finally
Python Modern C++
def mean(seq):
n = 0.0
for x in seq:
n += x
return n / len(seq)
auto mean(const Sequence& seq) {
auto n = 0.0;
for (auto x : seq)
n += x;
return n / seq.size();
}
using a concept
(note: not yet VC++)
automatic return
type deduction
Python Modern C++
def mean(seq):
return sum(seq) / len(seq)
mean = lambda seq: sum(seq) / len(seq)
auto mean(const Sequence& seq)
{ return reduce(begin(seq),end(seq)) / seq.size(); }
auto mean = [](const Sequence& seq)
{ return reduce(begin(seq),end(seq)) / seq.size(); }
Python C++17 with parallel STL
def mean(seq):
return sum(seq) / len(seq)
mean = lambda seq: sum(seq) / len(seq)
auto mean(const Sequence& seq) {
return reduce(par_unseq,begin(seq),end(seq))
/ seq.size();
}
auto mean = [](const Sequence& seq) {
return reduce(par_unseq,begin(seq),end(seq))
/ seq.size();
}
 What’s new?
 “Classic” vs. “Modern” C++
 Move semantics; vocabulary types
 “Top two” general issues/techniques
 RAII + scopes
 Error handling
 “One more”
 Pointers: Dumb and smart (and smart used correctly)
Then: C++98 code Now: Modern C++
set<widget>* load_huge_data() {
set<widget>* ret = new set<widget>();
// … load data and populate *ret …
return ret;
}
widgets = load_huge_data();
use(*widgets);
set<widget> load_huge_data() {
set<widget> ret;
// … load data and populate ret …
return ret;
}
widgets = load_huge_data();
use(widgets);
efficient, no deep copy
clean semantics of value types
+ efficiency of reference types
brittle
just asking for returned pointer to
be leaked, dangled, etc.
extra indirection throughout code
 string_view
 Non-owning const view of any contiguous sequence of characters.
 Variations for different character types (e.g., wide).
 optional<T>
 Contains a T value or “empty.”
 variant<Ts…>
 Contains one value of a fixed set of types.
 any
 Contains one value of any type, fully dynamic type.
 Non-owning const view of a contiguous sequence of characters.
 Note: NOT null-terminated.
 All these callers, and all their types… … can be made to work with:
std::wstring s; f(s);
wchar_t* s, size_t len; f({s,len});
winrt::hstring s; f(s);
QString s; f(s.toWStringView());
CStringW s; f((LPCSTR)s); void f(wstring_view s);
CComBSTR s; f({s.m_str, s.Length()});
BSTR s; f({s,SysStringLen(s)});
_bstr_t s; f({s,s.length()});
UNICODE_STRING s; f({s.Buffer, s.Length});
/* … known incomplete sample … */
 Contains a T value or “empty.”
std::optional<std::string> create() {
if (something) return “xyzzy”;
else return {}; // or std::nullopt
}
int main() {
auto result = create();
if (result) {
std::cout << *result << ‘n’; // ok
}
try { cout << *result; } // can throw
catch( const bad_optional_access& e) { /*...*/ }
cout << result.value_or(“empty”) << ‘n’; // if empty, prints “empty”
}
 Contains one value of a fixed set of types.
auto v = variant<int,double>(42); // v now holds an int
cout << get<int>(v); // ok, prints “42”
try {
cout << get<double>(v); // error, throws
}
catch( const bad_variant_access& e) {
cout << e.what();
}
v = 3.14159; // v now holds a double
cout << get<double>(v); // now ok, prints “3.14159”
 Contains one value of any type, fully dynamic type.
auto a = any(42); // a now holds an int
cout << any_cast<int>(a); // ok, prints “42”
try {
cout << any_cast<string>(a);// error, throws
}
catch( const bad_any_cast& e) {
cout << e.what();
}
a = “xyzzy”s; // a now holds a std::string
cout << any_cast<string>(a); // now ok, prints “xyzzy”
 What’s new?
 “Classic” vs. “Modern” C++
 Move semantics; vocabulary types
 “Top two” general issues/techniques
 RAII + scopes
 Error handling
 “One more”
 Pointers: Dumb and smart (and smart used correctly)
 Make sure that objects own resources. Pass every “new” object to the
constructor of an object that owns it (e.g., unique_ptr).
void f() {
auto p = make_unique<widget>(…);
my_class x( OpenFile() );
…
} // automatic destruction and deallocation, automatic exception safety
 What if there isn’t already an RAII type?
 Write one.
 Rarely, consider gsl::finally. It is intended as a last resort.
 Easy to abuse: In reviewed code, typically >50% of uses are abuses.
class widget {
private:
gadget g;
public:
void draw();
};
all types are
destructible
lifetime automatically
tied to enclosing object
no leak, exception safe
automatic propagation,
as if “widget.dispose()
{ g.dispose(); }”
void f() {
widget w;
:::
w.draw();
:::
}
lifetime automatically
tied to enclosing scope
constructs w, including
the w.g gadget member
automatic destruction
and deallocation for w
and w.g
automatic exception
safety, as if “finally {
w.g.dispose();
w.dispose(); }”
 Use exceptions/codes only to report errors, defined as the function can’t
do what it advertised (achieve documented success postconditions).
 Merriam-Webster: “an act that … fails to achieve what should be done”
 Much clearer than “use exceptions for exceptional situations.”
 Error codes vs. exceptions? No fundamental difference. Pick one (1).
 Prefer exceptions wherever possible:
 Error codes are ignored by default. (ouch)
 Error codes have to be manually propagated by intermediate code.
 Error codes don’t work well for errors in constructors and operators.
 Error codes interleave “normal” and “error handling” code.
 Use error codes on boundaries with non-C++ code (including C and DLL APIs).
 Precondition and postcondition violations should assert (or fail fast).
 They are logic bugs in the function caller and function callee body,
respectively, that should be reported at development time.
 Also, throwing an exception loses debug stack context.
 Postconditions should include or imply “!SUCCESS_EXIT ||”.
 It’s only a postcondition violation (bug in function body) if we’re returning
success.
 It’s never a postcondition violation if we’re reporting an error
(throwing an exception or returning a non-success code).
 Corollary: If we’re throwing an exception, we never need to explicitly write
“!SUCCESS_EXIT ||” on our postconditions because our success and failure
paths are already explicitly distinct (return vs. throw).
 What’s new?
 “Classic” vs. “Modern” C++
 Move semantics; vocabulary types
 “Top two” general issues/techniques
 RAII + scopes
 Error handling
 “One more”
 Pointers: Dumb and smart (and smart used correctly)
 C++98:
widget* factory();
void caller() {
widget* w = factory();
gadget* g = new gadget();
use( *w, *g );
delete g;
delete w;
}
red  now “mostly wrong” 
 Don’t use owning *, new, delete.
 Except: Encapsulated inside impl
of low-level data structures.
 Modern C++:
unique_ptr<widget> factory();
void caller() {
auto w = factory();
auto g = make_unique<gadget>();
use( *w, *g );
}
 For “new”, use make_unique by default,
make_shared if it will be shared.
 For “delete”, write nothing.
 C++98 “Classic”:
void f( widget& w ) { // if required
use(w);
}
void g( widget* w ) { // if optional
if(w) use(*w);
}
 Modern C++ “Still Classic”:
void f( widget& w ) { // if required
use(w);
}
void g( widget* w ) { // if optional
if(w) use(*w);
}
auto upw = make_unique<widget>();
…
f( *upw );
auto spw = make_shared<widget>();
…
g( spw.get() );
* and & FTW
 Derived-to-base just works:
// void f(const shared_ptr<Base>&);
f( make_shared<Derived>() ); // ok
 Non-const-to-const just works:
// void f(const shared_ptr<const Node>&);
f( make_shared<Node>() ); // ok
 Bonus geek cred if you know the aliasing ctor:
struct Node { Data data; };
shared_ptr<Data> get_data(const shared_ptr<Node>& pn) {
return { pn, &(pn->data) }; // ok
} Node
Data
 Antipattern #1: Parameters
(Note: Any refcounted pointer type.)
void f( refcnt_ptr<widget>& w ) {
use(*w);
} // ?
void f( refcnt_ptr<widget> w ) {
use(*w);
} // ?!?!
 Antipattern #2: Loops
(Note: Any refcounted pointer type.)
refcnt_ptr<widget> w = …;
for( auto& e: baz ) {
auto w2 = w;
use(w2, *w, *w2, whatever);
} // ?!?!?!?!
Example (HT: Andrei Alexandrescu): In late
2013, Facebook RocksDB changed pass-by-
value shared_ptr to pass-*/&.
 4 QPS (100K to 400K) in one benchmark
Example: C++/WinRT factory cache was slow.
“Obvious” suspect: cache’s mutex lock
Actual culprit: >50% time spent in extra
AddRef/Release on returned object
 The reentrancy pitfall (simplified):
// global (static or heap), or aliased local
… shared_ptr<widget> other_p …
void f( widget& w ) {
g();
use(w);
}
void g() {
other_p = … ;
}
void my_code() {
f( *other_p ); // passing *nonlocal
} // should not pass code review
 “Pin” using unaliased local copy.
// global (static or heap), or aliased local
… shared_ptr<widget> other_p …
void f( widget& w ) {
g();
use(w);
}
void g() {
other_p = … ;
}
void my_code() {
auto pin = other_p; // 1 ++ for whole tree
f( *pin ); // ok, *local
}
 The reentrancy pitfall (simplified):
// global (static or heap), or aliased local
… shared_ptr<widget> other_p …
void f( widget& w ) {
g();
use(w);
}
void g() {
other_p = … ;
}
void my_code() {
f( *other_p ); // passing *nonlocal
other_p->foo(); // (or nonlocal->)
} // should not pass code review
 “Pin” using unaliased local copy.
// global (static or heap), or aliased local
… shared_ptr<widget> other_p …
void f( widget& w ) {
g();
use(w);
}
void g() {
other_p = … ;
}
void my_code() {
auto pin = other_p; // 1 ++ for whole tree
f( *pin ); // ok, *local
pin->foo(); // ok, local->
}
unique_ptr<widget> factory(); // source – produces widget
void sink( unique_ptr<widget> ); // sink – consumes widget
void reseat( unique_ptr<widget>& ); // “will” or “might” reseat ptr
void thinko( const unique_ptr<widget>& ); // usually not what you want
shared_ptr<widget> factory(); // source + shared ownership
// when you know it will be shared, perhaps by factory itself
void share( shared_ptr<widget> ); // share – “will” retain refcount
void reseat( shared_ptr<widget>& ); // “might” reseat ptr
void may_share( const shared_ptr<widget>& ); // “might” retain refcount
1. Never pass smart pointers (by value or by reference) unless you actually
want to manipulate the pointer  store, change, or let go of a reference.
 Prefer passing objects by * or & as usual – just like always.
 Remember: Take unaliased+local copy at the top of a call tree, don’t pass f(*other_p).
 Else if you do want to manipulate lifetime, great, do it as on previous slide.
2. Express ownership using unique_ptr wherever possible, including when
you don’t know whether the object will actually ever be shared.
 It’s free = exactly the cost of a raw pointer, by design.
 It’s safe = better than a raw pointer, including exception-safe.
 It’s declarative = expresses intended uniqueness and source/sink semantics.
 It removes many (often most) objects out of the ref counted population.
3. Else use make_shared up front wherever possible, if object will be shared.
 What’s new?
 “Classic” vs. “Modern” C++
 Move semantics; vocabulary types
 “Top two” general issues/techniques
 RAII + scopes
 Error handling
 “One more”
 Pointers: Dumb and smart (and smart used correctly)
 … and it turns out we’ve already been doing it.
 Given a set<string> myset, consider:
// C++98
pair<set<string>::iterator,bool> result = myset.insert( “Hello” );
if (result.second) do_something_with( result.first ); // workaround
// C++11 – sweet backward compat
auto result = myset.insert( “Hello” ); // nicer syntax, and the
if (result.second) do_something_with( result.first ); // workaround still works
// C++17
auto [ iter, success ] = myset.insert( “Hello” ); // normal return value
if (success) do_something_with( iter );
BRK2146
How to Adopt Modern C++17 into Your C++ Code

More Related Content

What's hot

C++ Introduction
C++ IntroductionC++ Introduction
C++ Introduction
parmsidhu
 
T02 a firstcprogram
T02 a firstcprogramT02 a firstcprogram
T02 a firstcprogram
princepavan
 

What's hot (17)

C++ Introduction
C++ IntroductionC++ Introduction
C++ Introduction
 
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source Code
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source CodeA Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source Code
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source Code
 
Technical aptitude Test 1 CSE
Technical aptitude Test 1 CSETechnical aptitude Test 1 CSE
Technical aptitude Test 1 CSE
 
How to avoid bugs using modern C++
How to avoid bugs using modern C++How to avoid bugs using modern C++
How to avoid bugs using modern C++
 
C++17 std::filesystem - Overview
C++17 std::filesystem - OverviewC++17 std::filesystem - Overview
C++17 std::filesystem - Overview
 
C
CC
C
 
E5
E5E5
E5
 
C tutorial
C tutorialC tutorial
C tutorial
 
C __paper.docx_final
C __paper.docx_finalC __paper.docx_final
C __paper.docx_final
 
Virtual Method Table and accident prevention
Virtual Method Table and accident preventionVirtual Method Table and accident prevention
Virtual Method Table and accident prevention
 
Checking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-xChecking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-x
 
Types, classes and concepts
Types, classes and conceptsTypes, classes and concepts
Types, classes and concepts
 
T02 a firstcprogram
T02 a firstcprogramT02 a firstcprogram
T02 a firstcprogram
 
Cat's anatomy
Cat's anatomyCat's anatomy
Cat's anatomy
 
Analyzing the Quake III Arena GPL project
Analyzing the Quake III Arena GPL projectAnalyzing the Quake III Arena GPL project
Analyzing the Quake III Arena GPL project
 
Puzles C#
Puzles C#Puzles C#
Puzles C#
 
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
 

Similar to How to Adopt Modern C++17 into Your C++ Code

(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
Phil Calçado
 

Similar to How to Adopt Modern C++17 into Your C++ Code (20)

Vocabulary Types in C++17
Vocabulary Types in C++17Vocabulary Types in C++17
Vocabulary Types in C++17
 
Oh Crap, I Forgot (Or Never Learned) C! [CodeMash 2010]
Oh Crap, I Forgot (Or Never Learned) C! [CodeMash 2010]Oh Crap, I Forgot (Or Never Learned) C! [CodeMash 2010]
Oh Crap, I Forgot (Or Never Learned) C! [CodeMash 2010]
 
Glimpses of C++0x
Glimpses of C++0xGlimpses of C++0x
Glimpses of C++0x
 
Cpp17 and Beyond
Cpp17 and BeyondCpp17 and Beyond
Cpp17 and Beyond
 
Billing in a supermarket c++
Billing in a supermarket c++Billing in a supermarket c++
Billing in a supermarket c++
 
C++ Language
C++ LanguageC++ Language
C++ Language
 
C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0
 
Big Brother helps you
Big Brother helps youBig Brother helps you
Big Brother helps you
 
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
 
Hidden Dragons of CGO
Hidden Dragons of CGOHidden Dragons of CGO
Hidden Dragons of CGO
 
Anomalies in X-Ray Engine
Anomalies in X-Ray EngineAnomalies in X-Ray Engine
Anomalies in X-Ray Engine
 
Java Generics
Java GenericsJava Generics
Java Generics
 
Introduction to Dart
Introduction to DartIntroduction to Dart
Introduction to Dart
 
Headache from using mathematical software
Headache from using mathematical softwareHeadache from using mathematical software
Headache from using mathematical software
 
Summary of C++17 features
Summary of C++17 featuresSummary of C++17 features
Summary of C++17 features
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
 
Cpp tutorial
Cpp tutorialCpp tutorial
Cpp tutorial
 
Cross Platform App Development with C++
Cross Platform App Development with C++Cross Platform App Development with C++
Cross Platform App Development with C++
 
为什么 rust-lang 吸引我?
为什么 rust-lang 吸引我?为什么 rust-lang 吸引我?
为什么 rust-lang 吸引我?
 
Of complicacy of programming, or won't C# save us?
Of complicacy of programming, or won't C# save us?Of complicacy of programming, or won't C# save us?
Of complicacy of programming, or won't C# save us?
 

More from Microsoft Tech Community

More from Microsoft Tech Community (20)

100 ways to use Yammer
100 ways to use Yammer100 ways to use Yammer
100 ways to use Yammer
 
10 Yammer Group Suggestions
10 Yammer Group Suggestions10 Yammer Group Suggestions
10 Yammer Group Suggestions
 
Removing Security Roadblocks to IoT Deployment Success
Removing Security Roadblocks to IoT Deployment SuccessRemoving Security Roadblocks to IoT Deployment Success
Removing Security Roadblocks to IoT Deployment Success
 
Building mobile apps with Visual Studio and Xamarin
Building mobile apps with Visual Studio and XamarinBuilding mobile apps with Visual Studio and Xamarin
Building mobile apps with Visual Studio and Xamarin
 
Best practices with Microsoft Graph: Making your applications more performant...
Best practices with Microsoft Graph: Making your applications more performant...Best practices with Microsoft Graph: Making your applications more performant...
Best practices with Microsoft Graph: Making your applications more performant...
 
Interactive emails in Outlook with Adaptive Cards
Interactive emails in Outlook with Adaptive CardsInteractive emails in Outlook with Adaptive Cards
Interactive emails in Outlook with Adaptive Cards
 
Unlocking security insights with Microsoft Graph API
Unlocking security insights with Microsoft Graph APIUnlocking security insights with Microsoft Graph API
Unlocking security insights with Microsoft Graph API
 
Break through the serverless barriers with Durable Functions
Break through the serverless barriers with Durable FunctionsBreak through the serverless barriers with Durable Functions
Break through the serverless barriers with Durable Functions
 
Multiplayer Server Scaling with Azure Container Instances
Multiplayer Server Scaling with Azure Container InstancesMultiplayer Server Scaling with Azure Container Instances
Multiplayer Server Scaling with Azure Container Instances
 
Explore Azure Cosmos DB
Explore Azure Cosmos DBExplore Azure Cosmos DB
Explore Azure Cosmos DB
 
Media Streaming Apps with Azure and Xamarin
Media Streaming Apps with Azure and XamarinMedia Streaming Apps with Azure and Xamarin
Media Streaming Apps with Azure and Xamarin
 
DevOps for Data Science
DevOps for Data ScienceDevOps for Data Science
DevOps for Data Science
 
Real-World Solutions with PowerApps: Tips & tricks to manage your app complexity
Real-World Solutions with PowerApps: Tips & tricks to manage your app complexityReal-World Solutions with PowerApps: Tips & tricks to manage your app complexity
Real-World Solutions with PowerApps: Tips & tricks to manage your app complexity
 
Azure Functions and Microsoft Graph
Azure Functions and Microsoft GraphAzure Functions and Microsoft Graph
Azure Functions and Microsoft Graph
 
Ingestion in data pipelines with Managed Kafka Clusters in Azure HDInsight
Ingestion in data pipelines with Managed Kafka Clusters in Azure HDInsightIngestion in data pipelines with Managed Kafka Clusters in Azure HDInsight
Ingestion in data pipelines with Managed Kafka Clusters in Azure HDInsight
 
Getting Started with Visual Studio Tools for AI
Getting Started with Visual Studio Tools for AIGetting Started with Visual Studio Tools for AI
Getting Started with Visual Studio Tools for AI
 
Using AML Python SDK
Using AML Python SDKUsing AML Python SDK
Using AML Python SDK
 
Mobile Workforce Location Tracking with Bing Maps
Mobile Workforce Location Tracking with Bing MapsMobile Workforce Location Tracking with Bing Maps
Mobile Workforce Location Tracking with Bing Maps
 
Cognitive Services Labs in action Anomaly detection
Cognitive Services Labs in action Anomaly detectionCognitive Services Labs in action Anomaly detection
Cognitive Services Labs in action Anomaly detection
 
Speech Devices SDK
Speech Devices SDKSpeech Devices SDK
Speech Devices SDK
 

Recently uploaded

Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlFuture Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Peter Udo Diehl
 
Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
Bhaskar Mitra
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 

Recently uploaded (20)

IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxIOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 
Demystifying gRPC in .Net by John Staveley
Demystifying gRPC in .Net by John StaveleyDemystifying gRPC in .Net by John Staveley
Demystifying gRPC in .Net by John Staveley
 
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlFuture Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
UiPath Test Automation using UiPath Test Suite series, part 1
UiPath Test Automation using UiPath Test Suite series, part 1UiPath Test Automation using UiPath Test Suite series, part 1
UiPath Test Automation using UiPath Test Suite series, part 1
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptxUnpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
Quantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIsQuantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIs
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
 

How to Adopt Modern C++17 into Your C++ Code

  • 1.
  • 3.  What’s new?  “Classic” vs. “Modern” C++  Move semantics; vocabulary types  “Top two” general issues/techniques  RAII + scopes  Error handling  “One more”  Pointers: Dumb and smart (and smart used correctly)
  • 4.  “What should every C++ programmer be expected to know?”  For years, there has not been a single source to point to.  Now there is. Readable on a long plane flight.  Recommend it heavily!  Also a demonstration that modern C++ is simpler to teach and explain.  Currently being updated for C++17, Second Edition ETA July 2018.
  • 5. Then: C++98 code circle* p = new circle( 42 ); vector<shape*> v = load_shapes(); for( vector<shape*>::iterator i=v.begin(); i!=v.end(); ++i ){ if( *i && **i == *p ) cout << **i << “ is a matchn”; } // … later, possibly elsewhere … for( vector<shape*>::iterator i = v.begin(); i != v.end(); ++i ) { delete *i; } delete p;
  • 6. Then: C++98 code Now: Modern C++ circle* p = new circle( 42 ); vector<shape*> v = load_shapes(); for( vector<shape*>::iterator i=v.begin(); i!=v.end(); ++i ){ if( *i && **i == *p ) cout << **i << “ is a matchn”; } // … later, possibly elsewhere … for( vector<shape*>::iterator i = v.begin(); i != v.end(); ++i ) { delete *i; } delete p; auto p = make_shared<circle>( 42 ); auto v = load_shapes(); for( auto& s : v ) { if( s && *s == *p ) cout << *s << “ is a matchn”; } T*  shared_ptr<T> new  make_unique or make_shared no need for “delete” – automatic lifetime management exception-safe range-for auto type deduction not exception-safe missing try/catch, __try/__finally
  • 7. Python Modern C++ def mean(seq): n = 0.0 for x in seq: n += x return n / len(seq) auto mean(const Sequence& seq) { auto n = 0.0; for (auto x : seq) n += x; return n / seq.size(); } using a concept (note: not yet VC++) automatic return type deduction
  • 8. Python Modern C++ def mean(seq): return sum(seq) / len(seq) mean = lambda seq: sum(seq) / len(seq) auto mean(const Sequence& seq) { return reduce(begin(seq),end(seq)) / seq.size(); } auto mean = [](const Sequence& seq) { return reduce(begin(seq),end(seq)) / seq.size(); }
  • 9. Python C++17 with parallel STL def mean(seq): return sum(seq) / len(seq) mean = lambda seq: sum(seq) / len(seq) auto mean(const Sequence& seq) { return reduce(par_unseq,begin(seq),end(seq)) / seq.size(); } auto mean = [](const Sequence& seq) { return reduce(par_unseq,begin(seq),end(seq)) / seq.size(); }
  • 10.  What’s new?  “Classic” vs. “Modern” C++  Move semantics; vocabulary types  “Top two” general issues/techniques  RAII + scopes  Error handling  “One more”  Pointers: Dumb and smart (and smart used correctly)
  • 11. Then: C++98 code Now: Modern C++ set<widget>* load_huge_data() { set<widget>* ret = new set<widget>(); // … load data and populate *ret … return ret; } widgets = load_huge_data(); use(*widgets); set<widget> load_huge_data() { set<widget> ret; // … load data and populate ret … return ret; } widgets = load_huge_data(); use(widgets); efficient, no deep copy clean semantics of value types + efficiency of reference types brittle just asking for returned pointer to be leaked, dangled, etc. extra indirection throughout code
  • 12.  string_view  Non-owning const view of any contiguous sequence of characters.  Variations for different character types (e.g., wide).  optional<T>  Contains a T value or “empty.”  variant<Ts…>  Contains one value of a fixed set of types.  any  Contains one value of any type, fully dynamic type.
  • 13.  Non-owning const view of a contiguous sequence of characters.  Note: NOT null-terminated.  All these callers, and all their types… … can be made to work with: std::wstring s; f(s); wchar_t* s, size_t len; f({s,len}); winrt::hstring s; f(s); QString s; f(s.toWStringView()); CStringW s; f((LPCSTR)s); void f(wstring_view s); CComBSTR s; f({s.m_str, s.Length()}); BSTR s; f({s,SysStringLen(s)}); _bstr_t s; f({s,s.length()}); UNICODE_STRING s; f({s.Buffer, s.Length}); /* … known incomplete sample … */
  • 14.  Contains a T value or “empty.” std::optional<std::string> create() { if (something) return “xyzzy”; else return {}; // or std::nullopt } int main() { auto result = create(); if (result) { std::cout << *result << ‘n’; // ok } try { cout << *result; } // can throw catch( const bad_optional_access& e) { /*...*/ } cout << result.value_or(“empty”) << ‘n’; // if empty, prints “empty” }
  • 15.  Contains one value of a fixed set of types. auto v = variant<int,double>(42); // v now holds an int cout << get<int>(v); // ok, prints “42” try { cout << get<double>(v); // error, throws } catch( const bad_variant_access& e) { cout << e.what(); } v = 3.14159; // v now holds a double cout << get<double>(v); // now ok, prints “3.14159”
  • 16.  Contains one value of any type, fully dynamic type. auto a = any(42); // a now holds an int cout << any_cast<int>(a); // ok, prints “42” try { cout << any_cast<string>(a);// error, throws } catch( const bad_any_cast& e) { cout << e.what(); } a = “xyzzy”s; // a now holds a std::string cout << any_cast<string>(a); // now ok, prints “xyzzy”
  • 17.  What’s new?  “Classic” vs. “Modern” C++  Move semantics; vocabulary types  “Top two” general issues/techniques  RAII + scopes  Error handling  “One more”  Pointers: Dumb and smart (and smart used correctly)
  • 18.  Make sure that objects own resources. Pass every “new” object to the constructor of an object that owns it (e.g., unique_ptr). void f() { auto p = make_unique<widget>(…); my_class x( OpenFile() ); … } // automatic destruction and deallocation, automatic exception safety  What if there isn’t already an RAII type?  Write one.  Rarely, consider gsl::finally. It is intended as a last resort.  Easy to abuse: In reviewed code, typically >50% of uses are abuses.
  • 19. class widget { private: gadget g; public: void draw(); }; all types are destructible lifetime automatically tied to enclosing object no leak, exception safe automatic propagation, as if “widget.dispose() { g.dispose(); }” void f() { widget w; ::: w.draw(); ::: } lifetime automatically tied to enclosing scope constructs w, including the w.g gadget member automatic destruction and deallocation for w and w.g automatic exception safety, as if “finally { w.g.dispose(); w.dispose(); }”
  • 20.  Use exceptions/codes only to report errors, defined as the function can’t do what it advertised (achieve documented success postconditions).  Merriam-Webster: “an act that … fails to achieve what should be done”  Much clearer than “use exceptions for exceptional situations.”  Error codes vs. exceptions? No fundamental difference. Pick one (1).  Prefer exceptions wherever possible:  Error codes are ignored by default. (ouch)  Error codes have to be manually propagated by intermediate code.  Error codes don’t work well for errors in constructors and operators.  Error codes interleave “normal” and “error handling” code.  Use error codes on boundaries with non-C++ code (including C and DLL APIs).
  • 21.  Precondition and postcondition violations should assert (or fail fast).  They are logic bugs in the function caller and function callee body, respectively, that should be reported at development time.  Also, throwing an exception loses debug stack context.  Postconditions should include or imply “!SUCCESS_EXIT ||”.  It’s only a postcondition violation (bug in function body) if we’re returning success.  It’s never a postcondition violation if we’re reporting an error (throwing an exception or returning a non-success code).  Corollary: If we’re throwing an exception, we never need to explicitly write “!SUCCESS_EXIT ||” on our postconditions because our success and failure paths are already explicitly distinct (return vs. throw).
  • 22.  What’s new?  “Classic” vs. “Modern” C++  Move semantics; vocabulary types  “Top two” general issues/techniques  RAII + scopes  Error handling  “One more”  Pointers: Dumb and smart (and smart used correctly)
  • 23.  C++98: widget* factory(); void caller() { widget* w = factory(); gadget* g = new gadget(); use( *w, *g ); delete g; delete w; } red  now “mostly wrong”   Don’t use owning *, new, delete.  Except: Encapsulated inside impl of low-level data structures.  Modern C++: unique_ptr<widget> factory(); void caller() { auto w = factory(); auto g = make_unique<gadget>(); use( *w, *g ); }  For “new”, use make_unique by default, make_shared if it will be shared.  For “delete”, write nothing.
  • 24.  C++98 “Classic”: void f( widget& w ) { // if required use(w); } void g( widget* w ) { // if optional if(w) use(*w); }  Modern C++ “Still Classic”: void f( widget& w ) { // if required use(w); } void g( widget* w ) { // if optional if(w) use(*w); } auto upw = make_unique<widget>(); … f( *upw ); auto spw = make_shared<widget>(); … g( spw.get() ); * and & FTW
  • 25.  Derived-to-base just works: // void f(const shared_ptr<Base>&); f( make_shared<Derived>() ); // ok  Non-const-to-const just works: // void f(const shared_ptr<const Node>&); f( make_shared<Node>() ); // ok  Bonus geek cred if you know the aliasing ctor: struct Node { Data data; }; shared_ptr<Data> get_data(const shared_ptr<Node>& pn) { return { pn, &(pn->data) }; // ok } Node Data
  • 26.  Antipattern #1: Parameters (Note: Any refcounted pointer type.) void f( refcnt_ptr<widget>& w ) { use(*w); } // ? void f( refcnt_ptr<widget> w ) { use(*w); } // ?!?!  Antipattern #2: Loops (Note: Any refcounted pointer type.) refcnt_ptr<widget> w = …; for( auto& e: baz ) { auto w2 = w; use(w2, *w, *w2, whatever); } // ?!?!?!?! Example (HT: Andrei Alexandrescu): In late 2013, Facebook RocksDB changed pass-by- value shared_ptr to pass-*/&.  4 QPS (100K to 400K) in one benchmark Example: C++/WinRT factory cache was slow. “Obvious” suspect: cache’s mutex lock Actual culprit: >50% time spent in extra AddRef/Release on returned object
  • 27.  The reentrancy pitfall (simplified): // global (static or heap), or aliased local … shared_ptr<widget> other_p … void f( widget& w ) { g(); use(w); } void g() { other_p = … ; } void my_code() { f( *other_p ); // passing *nonlocal } // should not pass code review  “Pin” using unaliased local copy. // global (static or heap), or aliased local … shared_ptr<widget> other_p … void f( widget& w ) { g(); use(w); } void g() { other_p = … ; } void my_code() { auto pin = other_p; // 1 ++ for whole tree f( *pin ); // ok, *local }
  • 28.  The reentrancy pitfall (simplified): // global (static or heap), or aliased local … shared_ptr<widget> other_p … void f( widget& w ) { g(); use(w); } void g() { other_p = … ; } void my_code() { f( *other_p ); // passing *nonlocal other_p->foo(); // (or nonlocal->) } // should not pass code review  “Pin” using unaliased local copy. // global (static or heap), or aliased local … shared_ptr<widget> other_p … void f( widget& w ) { g(); use(w); } void g() { other_p = … ; } void my_code() { auto pin = other_p; // 1 ++ for whole tree f( *pin ); // ok, *local pin->foo(); // ok, local-> }
  • 29. unique_ptr<widget> factory(); // source – produces widget void sink( unique_ptr<widget> ); // sink – consumes widget void reseat( unique_ptr<widget>& ); // “will” or “might” reseat ptr void thinko( const unique_ptr<widget>& ); // usually not what you want shared_ptr<widget> factory(); // source + shared ownership // when you know it will be shared, perhaps by factory itself void share( shared_ptr<widget> ); // share – “will” retain refcount void reseat( shared_ptr<widget>& ); // “might” reseat ptr void may_share( const shared_ptr<widget>& ); // “might” retain refcount
  • 30. 1. Never pass smart pointers (by value or by reference) unless you actually want to manipulate the pointer  store, change, or let go of a reference.  Prefer passing objects by * or & as usual – just like always.  Remember: Take unaliased+local copy at the top of a call tree, don’t pass f(*other_p).  Else if you do want to manipulate lifetime, great, do it as on previous slide. 2. Express ownership using unique_ptr wherever possible, including when you don’t know whether the object will actually ever be shared.  It’s free = exactly the cost of a raw pointer, by design.  It’s safe = better than a raw pointer, including exception-safe.  It’s declarative = expresses intended uniqueness and source/sink semantics.  It removes many (often most) objects out of the ref counted population. 3. Else use make_shared up front wherever possible, if object will be shared.
  • 31.  What’s new?  “Classic” vs. “Modern” C++  Move semantics; vocabulary types  “Top two” general issues/techniques  RAII + scopes  Error handling  “One more”  Pointers: Dumb and smart (and smart used correctly)
  • 32.
  • 33.  … and it turns out we’ve already been doing it.  Given a set<string> myset, consider: // C++98 pair<set<string>::iterator,bool> result = myset.insert( “Hello” ); if (result.second) do_something_with( result.first ); // workaround // C++11 – sweet backward compat auto result = myset.insert( “Hello” ); // nicer syntax, and the if (result.second) do_something_with( result.first ); // workaround still works // C++17 auto [ iter, success ] = myset.insert( “Hello” ); // normal return value if (success) do_something_with( iter );