
How to Adopt Modern C++17 into Your C++ Code [video] - pjmlp
https://www.youtube.com/watch?v=UsrHQAzSXkA
======
cominous
C++17 is definitely going in the right direction for most applications. But I
have the feeling, that the compiler implementations cannot catch up with the
modernization speed.

We are using C++ for embedded devices and recognize a steady code bloat with
every release since C++11 (especially with C++17) without using any of the new
features (with gcc/clang). This is a trust-killer and actually the reason we
stay on C++11 for embedded development.

~~~
dvfjsdhgfv
Just curious: why did you choose C++ instead of C for embedded? Most shops I
know chose C just because of code bloat.

~~~
cominous
I have to admit, that C++ is still not the industry "Go-To" language for
embedded. But if you apply modern C++ correctly, there is very few overhead
compared to C and the software is much easier to maintain.

The performance of embedded MCU's are continuously rising over the years and
that little overhead is buying development speed.

Not to mention smart pointers, templates and constexpr making my life easier.

The only real issue with C++ is, that as soon as you get into serious embedded
applications, you have restrictions when it comes to heap usage e.g. in
medical devices using the heap is forbidden. So you cant use the STL.

There is a promising embedded STL project, but it's not there yet:
[https://www.etlcpp.com](https://www.etlcpp.com)

~~~
Const-me
> So you cant use the STL.

std::array is in there since C++ 11 and it doesn’t use heap.

And/or you can use STL with custom allocators that work without heap. We did
something similar developing for Nintendo Wii console. There was a heap but we
didn’t want to use it to avoid memory fragmentation. AFAIR we used two arenas
(essentially stacks), one very small for temporary data cleaned up at the
start of each frame, and a large one cleaned up when a level is unloaded.

However, I don’t have hands on experience developing firmware for medical
devices, so I’m not sure it’ll work for them.

~~~
AnimalMuppet
The problem for medical devices isn't so much whether custom allocators will
_work_. The problem is whether the FDA will freak out because you're not
following industry-best-practice coding guidelines.

~~~
ska
That's really not how it works. The FDA is fundamentally concerned about two
things, safety and efficacy. You need a plan to demonstrate the latter, and
you need your quality system, SDP, etc. to demonstrate how you approach the
former. This is about good engineering practices, not particular
implementation techniques.

So you can do things many different ways. If you do say "we do this like X,
which is industry standard, just like T, U, and V do" it's a simpler argument
than "we do this like Y. Lots of people do X, but here is how we have
demonstrated Y is better for us...". But this can be fine too, just possibly
more work.

Also worth noting (a) there is no industry-wide best practices agreement (b)
there is no FDA wide agreement on what should be done (different device types
are reviewed by different panels (c) the FDA doesn't understand software
development deeply across it's panels, but it is catching up.

~~~
AnimalMuppet
Sure, that's all true. I'm looking at the "simpler argument" part.

It's especially true if you're saying "This new device is just like our
previous device, with these few small changes". (I forget what that's called,
but you can do a lot less paperwork if that's true.) But if you start doing
memory allocations where you never did before, they're probably going to want
to apply higher scrutiny to your entire software. That's... painful.

~~~
ska
You are possibly thinking about note-to-file (which isn’t quite the process
any more, but similar)

But it is worth pointing out, FDA (or other national body) isn’t doing code
reviews. They are mostly interested in process , and how you follow it. The
place where this really interacts s is hazard analysis, and then it’s just up
to you to demonstrate your checks and balances.

------
zengid
::Somewhat tangential anecdote and plea for advice::

I just finished my third semester of using C++ (with Data structures 1) and we
use _NO_ modern stuff in class [1]. Raw pointers. New and delete. No Lambdas
(although we learned about function pointers, though not function objects). I
completely understand _why_ (we're learning low level stuff and it's worked
for the last 30 years so whatever), but now I'm trying to ramp up and learn
modern C++ for a personal project I'd like to start working on (basically an
audio plugin using JUCE).

Here's what I've been doing to try and catch up (I have two weeks off before
my internship starts). I try to watch Bjarne and Herb's keynotes but they
often are speaking to an audience already familiar to modern C++, so this
posts video is great! I've discovered the brilliance of Sean Parent, so I'm
watching all of his talks. I've ordered Scott Meyers _Effective Modern C++_
(and hopefully he uses the money for a new haircut /s). I've browsed through
the C++ Core Guidelines [2]. I'm reading the JUCE tutorials (and source code)
which is beautifully written.

What are other good resources? I'm particularly interested in developing
GUI's. I'd like to see some tutorials written like Herbs talk here: for people
new to C++ _and_ new to modern C++.

[1] This is our textbook: [https://www.amazon.com/Programming-Program-Design-
Including-...](https://www.amazon.com/Programming-Program-Design-Including-
Structures/dp/1285852753)

[2]
[http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#...](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-introduction)

~~~
monocasa
Effective Modern C++ is a great book designed for "I learned pre C++11, but
now I want to get with the times, and specifically want to know the idiomatic
ways to apply it".

~~~
TomVDB
Is Effective Modern C++ good enough for those who learned C++ in the early
2000, still use those idioms and never upgraded to C++11 ?

~~~
blub
I'd recommend Bancila's Modern C++ Cookbook instead, it takes you through the
new features and explains how to use them.

Effective Modern C++ is part language tutorial, part series of tips, part
philosophical discussion on how one should use various features. It's not
appropriate as an intro to modern C++.

~~~
monocasa
> Effective Modern C++ is part language tutorial, part series of tips, part
> philosophical discussion on how one should use various features. It's not
> appropriate as an intro to modern C++.

See, I take the opposite stance. There's enough moving parts here that it's
nice to get some background into what's actually happening, and then read more
cookbook style stuff when you understand the underlying context.

------
saagarjha
Great talk, but I still have a couple questions that I'm sure someone here can
answer:

1\. I didn't see what the smart pointer stuff had to do with C++17. Aren't
these all available from C++11? Are these something new that I missed, or are
they just comments on how to avoid bugs, based on Herb Sutter's personal
experience?

2\. Should I std::string_view everywhere I used to use std::string now? The
examples given seemed to lean heavily towards using std::string_view as
parameters instead of std::string, but should I use them as a drop-in
replacement everywhere?

3\. The std::optional example looked really clunky, relying on checking an
exception. I see there are a bunch of nice operators and utility functions on
std::optional that cover some use cases, like coalescing, but will we get
something that allows for optional chaining?

~~~
masklinn
> 3\. The std::optional example looked really clunky, relying on checking an
> exception. I see there are a bunch of nice operators and utility functions
> on std::optional that cover some use cases, like coalescing, but will we get
> something that allows for optional chaining?

Nope. It must be understood that std::optional is not an Option type, its
purpose is not to have a way to express "missing" items _in a type-safe
manner_ but rather to have pointer-type semantics without needing to heap-
allocate. So you can just deref' an std::optional, and it's UB if they're
empty. Don't think of it as Haskell's Maybe, think of it as a stack-allocated
version of std::unique_ptr.

~~~
humanrebar
> ...its purpose is not to have a way to express "missing" items in a type-
> safe manner...

Except that's exactly why you would take an `optional<int>` as a parameter. To
avoid the ambiguity and possible bugs of taking an `int*`.

~~~
masklinn
> Except that's exactly why you would take an `optional<int>` as a parameter.

Except for the type-safe part which is the important bit (hence the _emphasis_
on it), and which std::optional does not provide.

> To avoid the ambiguity and possible bugs of taking an `int*`.

The only ambiguity and possible bug (singular) you're avoiding using
std::optional is the question of ownership. Because as emphasised in the
original comment std::optional is no more type-safe than a raw pointer.

~~~
humanrebar
Clarity about ownership is enough. But there's also ambiguity because pointers
are sometimes used to pass around arrays, especially in the case of 'char*'.
And a dev also has to go out of his way to create a dangling optional<int>.

Even if we consider just ambiguous ownership, there are a whole host of
behaviors that could result from that single design mistake, including
undefined behavior, which could include trashing your production database,
firing the missiles, or behaving as expected until an unrelated piece of code
changes a year later.

------
alexeiz
I just checked how many times I use explicit delete in my moderately sized 7K
LOC C++ project: just once. In code that interfaces with an old library.
Modern C++ is not only practical. It's easy.

~~~
thekingofh
You using smart pointers from C++11 or later?

~~~
alexeiz
Yes. But surprisingly not as often as I thought I would. Move semantics and
guaranteed copy elision allows to avoid pointers in many common situations.

~~~
vvanders
It's also better in that you can avoid cycle-leaking from your smart pointers.

~~~
thekingofh
I'm still having trouble seeing how move semantics and copy elision help me
get rid of smart pointers. I read up on it after reading these comments and
just still am not following. I see how move semantics avoid a copy, but if I'm
dealing with cases where multiple objects need to use or hold a reference to
the same object, how can move semantics help me do this? Seems good for
ensuring only one object contains the reference.

~~~
alexeiz
Notice that I didn't say all cases. Just the most common ones. When you
require shared ownership of an object, of course, you'd use an appropriate
smart pointer (shared_ptr). But shared ownership is not very common (well, at
least in the systems that I design). However before C++11/14, you had to use
pointers and heap allocated objects in cases that have nothing to do with
shared ownership because passing objects by value would incur a substantial
overhead. Now that we have move, copy elision and library classes like
std::optional (which I forgot to mention earlier) it's not the case any more.

~~~
thekingofh
Ah I'm following now. Transfer of stack references in cases where it's
unnecessary to share objects. Actually interesting that it raises the bar for
the need to allocate on the stack.

------
nebgnahz
I have struggled in the past to learn modern C++. I think the language is
pretty cool, but couldn't find good guide in learning about them.

Having used Rust for a year or so, now I look back at these features and they
seem quite natural. I have to say the documentations and tutorials from Rust
community is great. It might be a detour, but now I feel much more comfortable
reading modern C++ blogs and watch this video!

------
partycoder
I think it would be good to break backwards compatibility and start off clean
with what we know now in the form of a new language.

------
geokon
Link for those that can't use Youtube:
[https://channel9.msdn.com/Events/Build/2018/BRK2146](https://channel9.msdn.com/Events/Build/2018/BRK2146)

(also has download links)

------
ddtaylor
Sanity check, does gcc support all of these?

~~~
jchb
Yes, but the final version of the C++17 standard was released as late as
December 2017, so support may not be "production ready", neither in gcc nor in
other compilers.

You can the summary of the gcc c++ standard support here:
[https://gcc.gnu.org/projects/cxx-
status.html#cxx17](https://gcc.gnu.org/projects/cxx-status.html#cxx17). Full
support for all features in the c++17 standard, but the support is declared
"experimental".

Similarly here for clang:
[https://clang.llvm.org/cxx_status.html](https://clang.llvm.org/cxx_status.html)

And Visual studio:
[https://blogs.msdn.microsoft.com/vcblog/2018/04/26/announcin...](https://blogs.msdn.microsoft.com/vcblog/2018/04/26/announcing-
msvc-conforms-to-the-c-standard/) (link to latest blog post, perhaps there is
a status page that gets updated, but could not find it).

~~~
baking
Maybe I'm missing something, but
[http://en.cppreference.com/w/cpp/compiler_support](http://en.cppreference.com/w/cpp/compiler_support)
seems to have it all in one place.

~~~
pjmlp
It misses most of the compilers on the embedded space.

For example, TI still has some compilers stuck on C++98 and C++03.

[http://processors.wiki.ti.com/index.php/TI_Compilers_and_Ind...](http://processors.wiki.ti.com/index.php/TI_Compilers_and_Industry_Standards#C.2B.2B_standard)

------
rehemiau
Can I cheaply "pattern match" on variant type without involving exceptions or
dynamic cast etc?

~~~
mellery451
I think visit is what you want
([http://en.cppreference.com/w/cpp/utility/variant/visit](http://en.cppreference.com/w/cpp/utility/variant/visit)),
unless I misunderstand what you mean by "pattern match"

~~~
ninkendo
I used to keep pretty good track of what's been happening in c++, at least as
C++11 was being formalized, and I've read a good fraction of Effective Modern
C++, but...

I can't make heads or tails out of half of the code in that example. C++ has
become extremely hard to grok.

I mean, take these two lines:

    
    
        template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
        template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
    

What's even going on there? Inheriting from a variadic list of classes?
`using` a variadic list of parent functions, I guess? The second line looks
like it's defining a constructor function for the overloaded() struct, but
it's not implemented anywhere?

In the end there's magic code that looks like pattern matching, but I have no
idea how they got there.

~~~
alexeiz
> What's even going on there?

The first line defines 'struct overloaded' derived from all of its template
parameters. Template parameters are supposed to be functors (lambdas), so we
use their operator()'s in 'overloaded'.

The second line defines a template deduction guide for the 'overloaded'
constructor, which says: take types from the constructor arguments and use
them as the class template parameters.

The idea is to be able to construct 'overloaded' like this:

    
    
        overloaded{[](ArgT1 arg){/*lambda1*/},
                   [](ArgT2 arg){/*lambda2*/}, ...};

------
wpdev_63
People who are looking for a modern C++ should take a serious look at Rust. It
has all the things you want in modern C++ while getting rid of the cruft of
the language.

~~~
alexeiz
I'd love to. But seeing how Rust adopters struggle with something as trivial
as a linked list
([https://news.ycombinator.com/item?id=16442743](https://news.ycombinator.com/item?id=16442743)),
doesn't inspire me.

~~~
Retra
Linked lists are easy. People are struggling with _safe_ linked lists, because
they think they should be as easy to write as an _unsafe_ ones.

But if you're already willing to use C or C++, you've got no reason to avoid
unsafe.

