
C++17 – better than you might think - ingve
http://www.levelofindirection.com/journal/2016/12/28/c17-why-its-better-than-you-might-think.html
======
fauigerzigerk
There is one real problem with "modern" C++ that I would have hoped they would
focus on: Compile times.

All the new stuff is heavily template based. As more libraries are written in
that style, compile times go through the roof.

I wrote some code recently that required high precision monetary calculations.
So I used boost multiprecision. It turned out to be completely impossible as
most compilation units ended up depending on that library directly or
indirectly.

Already slow compiles became unbearably slow. Facing a tight deadline I
quickly wrote an extremely ugly, slow, error prone, pimpl based wrapper around
boost multiprecision. Many calculations now require dynamic memory allocation
for no good reason.

This is just terrible, because I know I can't leave it like this. I'm going to
have redesign the whole thing or look for other libraries or look a lot more
deeply into the calculations to see if they really cannot be done with large
integers.

It's a productivity disaster. You could say I made wrong choices, which is
true, but I think the C++ standards committee has been making wrong choices in
not prioritizing a fix for compile times (modules?).

What's the point of having nice new features if you end up spending half your
time on carefully cordoning off any code that uses them?

~~~
logicallee
holy cow, I never would have thought in 2016 compiling a C++ program could be
so slow that it makes it impossible for someone.

Can you put numbers on these figures? By "Unbearably slow" how many minutes
(or hours) did you mean? Do you use a heavy desktop with a fast SSD and a lot
of RAM?

Finally what is the total output program size (roughly). Like are we talking
about an application that is in the gigabytes, like the complete Adobe suite
or something?

I would like to know more information about how it's possible for this to
happen. tell us as much as possible :)

Thanks!

~~~
dibanez
As others have mentioned, I've resorted to brute force (parallel compile using
16 physical cores, good SSD, 32GB RAM). I have a 20KLOC library that I wrote
myself (very few templates), that takes 20 sec to compile in parallel, meaning
in serial it would take about 5 min. Then there is a giant 3MLOC system I work
with (much templating), that takes 20 min to compile in parallel (consuming
15GB RAM), meaning in serial it would take 6 hours. One can also see in this
3MLOC system that it is the last few small files that take the longest to
compile, because they include much of the rest of the system as template code
in headers.

~~~
thechao
Preprocess your source 'cat' the results together; then, hand off to the
compiler. On a 2015 MacBookPro I've seen upwards of 100kloc/s. Probably
average 30--60kloc/s. With ccache my 5mloc code base takes as little as 300ms
to do incremental compile & relink.

Another thing is to rely on the preprocessor for code generation; then you're
dealing with memory-speed elaboration of the AST, rather than reading off of
disk.

~~~
dibanez
I did the single file trick for the small library that I control, as a
configure option. It definitely does help, 2X speedup in serial compile time
typically. however, you lose the ability to compile in parallel, which with my
hardware gives a 16X speedup, so for now parallel compiles are the winner.

------
gurkendoktor
More features, more libraries, but is there a working group that looks back at
C++98 and tries to reduce complexity by removing mistakes from the language?

My pet peeve is Argument-Dependent Lookup. It's a hack that breaks the
encapsulation of namespaces, increases compile times and still makes it harder
to write code - try swap()ing two values of type T in a template function. But
like any of C++'s warts, it will be with us forever.

~~~
rl3
> _More features, more libraries, but is there a working group that looks back
> at C++98 and tries to reduce complexity by removing mistakes from the
> language?_

Then you break backwards compatibility. What about static analysis to enforce
a particular subset of features deemed idiomatic or otherwise best practice?

Granted, reducing complexity does make the job of future compiler authors far
less miserable.

~~~
ktRolster
_What about static analysis to enforce a particular subset of features deemed
idiomatic or otherwise best practice?_

I like that idea.

~~~
koja86
You might find this project kind of interesting:

[https://github.com/isocpp/CppCoreGuidelines/blob/master/CppC...](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md)

As a day-to-day C++ practitioner I like it.

...Yet I am not fully convinced that the general idea of language evolution
implemented as ruleset outside of the language itself is the way to go. Seems
more like band-aid to me and made me start to think about concept of
programming language's life cycle in context of Darwinian evolution - once
either legacy compatibility burden is too big or that particular biotope of
specific problems the language solves better than others vanishes/changes the
language dies out.

My particular issue with C++ is that it's complexity, longevity and evolution
made possible for widespread bad-practices as not every C++ developer evolved
as much as the language itself and it's general public understanding. (Some
current best-practices were simply not always widely known or accepted.) I
would even go as far to say that most of existing C++ code is crap (at least
from standpoint of today "modern" C++).

And that's why I am both eagerly looking to "next generation" being shaped up
by people who has (hopefully) learnt from past mistakes and used by people who
care (itching to give Rust a ride once it stabilizes just a bit more) and also
occasionally digging in the history for possible gems that I might not able to
see without my current experience (platonic weekends-only relationship with
Haskell, Lisp being right there at top of my TODO list).

EDIT: Removed the sir.

~~~
rl3
> _Sir, ..._

You may want to take a quick gander at the profile of whom you're replying to.
:)

> _... itching to give Rust a ride once it stabilizes just a bit more ..._

Likewise, though from my limited research it seems Rust has legacy baggage of
its own already, and there's difficulty in coming to a consensus on what
qualifies as idiomatic Rust. It seems that the same principle of cherry-
picking a subset of features would apply just the same to Rust as it does to
C++. The latter being _far_ messier, of course.

~~~
echelon
> _it seems Rust has legacy baggage of its own already_

What is considered legacy cruft in Rust? The only change I'm aware of was the
introduction of the `?` operator to replace the `try!` macro. That's easy to
find/replace.

~~~
rl3
The notion extends to official libraries, not just the language itself. That
said, I'm not the best person to ask, but cursory research turns up a few
examples.[0][1][2][3]

Some of these aren't examples of legacy cruft per se. However, as complexity
is added to a language at a rapid rate, there becomes more confusion over what
best practice actually is.

[0]
[https://www.reddit.com/r/rust/comments/2r7ttq/where_to_find_...](https://www.reddit.com/r/rust/comments/2r7ttq/where_to_find_idiomatic_rust_code_for_reference/)

[1] [https://users.rust-lang.org/t/rust-version-support-in-
librar...](https://users.rust-lang.org/t/rust-version-support-in-library-
crates-best-practices/4405)

[2]
[https://gist.github.com/lifthrasiir/cedb5db8dbcd209c5957](https://gist.github.com/lifthrasiir/cedb5db8dbcd209c5957)

[3] [https://users.rust-lang.org/t/is-this-idiomatic-
rust/2155](https://users.rust-lang.org/t/is-this-idiomatic-rust/2155)

------
daly
Back in the 70s IBM used a language called PL/I (aka "Pig Language for
Idiots). It had EVERYTHING. Every idea from every language showed up in PL/I.
Compiling on a 6Mhz IBM mainframe took a LONG time. The language was, for its
time, very complex.

We had one person in the building who was the PL/I guru. If you really needed
to understand something he could work out the answer. Everyone else chose a
simple subset of the language and never used the fancy features. Unfortunately
everyone chose different subsets so maintaining other people's code was a
pain.

C++ has the same problem; big, slow, and a collection of ideas imported from
other languages. For example, "concepts" have been proposed for the next
"standard". They appear to be lifted from Axiom's Spad language.

The C++ committee seems to feel that "importing" ideas is a way to make C++
into a better, newer "standard". Unfortunately that is simply causing havoc.
Forty year old code that no longer compiles because some bright spot decided
to change the semantics of "inline" is a huge waste of time.

Forty year old code in Common Lisp, which also has a standard, a single
standard, just works. The code is fast because there are years worth of
optimizations by the compiler writers.

C++ isn't a language. It is a laboratory where some people work out ways to do
poorly what other languages do well. C++ isn't a language. It is a parade of
languages with "standards". Do you really want to have to "fix" legacy working
code because it no longer works in C++21? Programming is hard enough. Fixing
old code because it "no longer conforms to the standard" is a huge,
unnecessary cost in both time and money. Use it at your own peril. Just be
aware that the code you write today won't compile next year.

~~~
jlg23
> Forty year old code in Common Lisp, which also has a standard, a single
> standard, just works.

Mostly. If not, just

    
    
        (pushnew :symbolics *features*)
    

or whatever the code was created on. Especially the very old lisp code
regularly needs some coercion to be made run on a standard compliant cl.

The "just works" part is proven wrong by the regularly reoccurring attempts to
agree on extensions to the standard and the myriads of libraries out there
that provide generic wrappers around implementation specifics.

> C++ isn't a language. It is a laboratory where some people work out ways to
> do poorly what other languages do well.

"Lisp isn't a language, it's a building material." \-- Alan Kay

and

"A poor coder can write poor code in any language." \-- me

~~~
Animats
Almost. I recently revived the original Boyer-Moore theorem prover from the
1992 sources. I had to make only one change to get it to run with Gnu Common
LISP. The name "EXECUTE" is now being used by a standard library, and I had to
rename a function.[1]

(It's fun running that on modern hardware. It was painfully slow when I ran
the original around 1980. Now it can prove the basic theorems of number theory
in a few seconds.)

[1] [https://github.com/John-Nagle/nqthm](https://github.com/John-Nagle/nqthm)

------
charles-salvia
So-called "modern C++" (basically C++11 and beyond) is really immensely more
pleasurable to work with than C++03/C++98.

The confluence of automatic type deduction, closures, and move semantics
turned C++ into the language that it really ought to have always been, given
the vision of Alexander Stepanov's STL. I mean really, before lambdas, using
the STL was often really clunky.

But even before C++11, the main "killer features" of C++ has always been RAII
(deterministic destruction of resources) and compile time duck typing
(templates.) These features together have always made C++ an incredibly
powerful language that lets you code at a high level of abstraction with zero
runtime penalty (at the cost of longer compile times).

Nowadays, C++ can be almost Pythonic in its expressiveness. But I agree that
the most urgent problem facing C++ is huge compile-times, which often result
from a combinatorial explosion of new types created by templates that
instantiate other templates, etc.

~~~
nnethercote
Move semantics are _so_ useful and powerful, but _so_ complex. I've read
multiple tutorials on them (all of them very long) and I still keep forgetting
minor but critical details.

(You could probably replace "move semantics" in that sentence with multiple
other C++ features and still have a valid statement.)

------
daurnimator
The thing I want most is for them to deprecate misfeatures. C++ code can be
impenetrable as the language is _so_ large and complex.

~~~
TillE
I never, ever hear this as a priority from fellow C++ programmers. It's always
just on HN.

If you're actually working with C++, old "misfeatures" simply aren't something
which gets in your way very often. You can just code in the modern way and be
happy.

~~~
codeflo
That's great for you, but unfortunately doesn't match my experience. Large,
old codebases tend to become a mix of all "eras" of C++. That's either because
old code was never completely reworked, or because newer programmers pick
stuff up in the wrong place, for example from an old blog post.

The problem then is that some of the advantages of modern C++ are a bit "all
or nothing". Just to pick an example, for exception safety in the current
sense to really work, basically all of your code has to be written in a
certain style, which is something that's really hard to achieve.

Maybe that's less of a problem for codebases started after 2011 that have been
written in the modern style from the beginning. But given the way the C++
language continues to evolve, my bet is that even those will eventually run
into the same problem with whatever new feature is introduced in 2026. There
really needs to be a way to deprecate old language features.

~~~
ansible
_Maybe that 's less of a problem for codebases started after 2011 that have
been written in the modern style from the beginning. But given the way the C++
language continues to evolve, my bet is that even those will eventually run
into the same problem with whatever new feature is introduced in 2026. There
really needs to be a way to deprecate old language features._

That's one of the things I think the golang project did right. The gofix tool
can be used to update old codebases.

------
bborud
To be truthful: the older and more experienced I get I can't help but wonder
why on earth people get so stuck in C++. To me the sheer weight and complexity
of C++ appears meaningless. We know better now than we did in the 80s. Yet
people spend their lives trying to fix C++.

Why?

~~~
IshKebab
Until Rust there was no real alternative. All other 'better' languages use a
garbage collector which is a no-go in most of the situations where C++ is
used.

~~~
loup-vaillant
C++ is often used in situations where a GC would have been perfectly fine.
I'll go as far as to guess that _most_ C++ projects are like this. In my
little corner of the world, C++ is one of the most overused languages.

~~~
IshKebab
Until relatively recently GC pauses have been a real problem. Java used to
have no upper bound on stop-the-world GC pauses - your program could literally
stop doing anything for an entire minute.

But these days GCs are much better, and especially with the Go GC having sub-
millisecond pauses I think you are right that most projects written in C++
_today_ could be written in Go. (And it seems like that is starting to
happen.)

------
eb0la
There is a good free eBook from O'Reilly about C++14 worth reading: "C++ The
Beast is Back"
[http://www.oreilly.com/programming/free/c++-today.csp](http://www.oreilly.com/programming/free/c++-today.csp)

------
ktRolster
I used to write C++ for a living, but now it's changed enough that I feel like
I don't even know the language anymore.

------
octoploid
Build-in sum types and pattern matching are the major missing features.

Instead C++17 will have library hacks like std::variant, that almost certainly
will be deprecated for C++20.

~~~
revelation
Modules seem much more important than either of those. You know where you
include a platform header and suddenly you can no longer call a variable "min"
because said platform header decided that should be a macro and it's giving
you cryptic errors because what you see isn't what the compiler sees.

I've written too much C++ to be dumbfounded by that stuff but that doesn't
mean I'm not still bitter about it.

~~~
loup-vaillant
> _Modules seem much more important than either of those._

Modules solve an immediate and obvious pain: unacceptably long compile times.
Sum types are more profound. Anyone having tasted an ML derivative (as I have)
would _dearly_ miss them. Seriously, once you've tasted sum types, you'll want
to use them _everywhere_ : option types, error returns, abstract syntax trees
(JSON, XML, compilers…), you name it, sum types probably solve it.

Sum types are no panacea, but if you squint your eyes just right they're
pretty damn close.

~~~
revelation
I've tasted sum types and if I was trying to be snarky I'd say so have
millions of Java enterprise developers who fill their code with a healthy dose
of _instanceof_ and _null_ :)

It is somewhat anathema to the OO idea and brings lots of (runtime)
implementation concerns so I can understand the delay.

------
alkonaut
I want a list of things removed not a list of things added.

Backwards compatibility is a strength, up to a point.

~~~
overgard
So, you want a language nobody will use. Look at how badly Python 3 turned
out, and it wasn't even that hard to port code.

~~~
tcbawo
My impression is that Python 3 finally has critical mass. After 3.5, most of
the heavy users I know have switched or are considering switching.

~~~
overgard
I hope so, but it was a sordid mess to get there.

~~~
BeetleB
I mean, was it?

My Linux system has both installed. Software that needs one or the other just
works.

I recently converted my scripts to Python3. I was shocked at how easy it was.
Didn't spend more than a few minutes on any given script.

No dependencies that I need that aren't in Python3.

------
bfrog
It's still C++ with all the baggage that comes with. Every company/project
seems to have their own subset they use. C++ isn't one language, it's dozens.

------
lngnmn
There is a nice way to realize how deeply wrong everything is with C++..

Suppose, I have a silly idea - I could recompile my mplayer+ffmpeg and,
perhaps, emacs with clang4 with all the cool optimizations for my cheap crappy
i3-6xxx CPU of my crappy Lenovo laptop. Seems like nobrainer. Now movies are
less laggy.

Why then wouldn't I recompile my mysql server with -stdlib=libc++ and
-std=c++1x, -rtlib=compile-rt, using lld and -lomp? _Oh fuck..._

~~~
AndyKelley
Can you elaborate?

~~~
lngnmn
The c++98 code cannot be linked to libc++ which is c++11.

C++ is a set of standardized kludges incompatible between standards.

------
NKCSS
I wonder why it feels like I can't move at the same pace with C++ compared to
C#; want to have a file copied to your output dir? Create a post-compile task;
with C# you can just set a property to 'copy always'. Want to add a reference?
Set up which dir's to look for, type names, etc. with C#: add reference,
choose your dll/whatever and you're done! And those are just a few. One of the
biggest hurdles with C++ is type conversion; I recently wrote a small app;
most time was spent writing functions to cast/convert all the 9000 ways to
define numbers and strings... It's when you start to appreciate the
System.Object model that makes sure everything can be represented as a Unicode
string that everything knows how to work with.

~~~
koja86
You are comparing apples to oranges here.

I also agree that type system in C++ is not perfect and is rarely used in a
sensible manner. Yet I would rather look for inspiration in functional
statically-typed languages rather than in specialized "multi-paradigm"
dynamically-typed ones.

~~~
NKCSS
I know it's not fair, but because I write identical apps in both languages,
it's one that comes to mind frequently and it becomes very apparent how
powerful C# is when it comes to Rapid Application Development.

------
creo
This is why in TLDR fashion: "[...] if you take them (promised big language
features) all together - or even just two or three of them - they have the
potential to change the language[...]"

------
tempodox
What's a “TS”?

~~~
fanf2
Looks like "technical specification", based on [http://open-
std.org/JTC1/SC22/WG21/](http://open-std.org/JTC1/SC22/WG21/)

------
tmsh
ccache and forward declarations / isolating classes that require use of large
header files to implementation files. Ie, spend 80% of your time working on
classes without deep header dependencies.

It's amortized O(k).

------
alextooter
The only problem of C++, it has a wrong Standards Committee.

~~~
koja86
Why so? Genuinely curious.

~~~
geezerjay
C++'s standardization committee is known for being enthusiastically pro-
Microsoft. IIRC, C++'s thread support is essentially the option that Microsoft
forced upon the standard, in detriment of ISO's very own pthreads library
which was already an ISO standard.

IIRC, the same problem also plagues C's committee.

~~~
Scea91
C++'s thread support is basically boost.thread with some differences. Can you
explain in which way is it Microsoft over pthreads?

------
faragon
Please, KISS, professor Stroustrup.

~~~
pklausler
You're asking somebody who makes money selling thick expensive self-
obsolescing books explaining an obscenely complicated programming language to
simplify the language?

------
sanatgersappa
C++: an octopus made by nailing extra legs onto a dog.

~~~
geezerjay
> C++: an octopus made by nailing extra legs onto a dog.

...and yet it's (arguably) the best software-writing tool that mankind has
invented, at least up to now.

~~~
swift
Arguably is an understatement. Though it's certainly true that there are some
problem domains in which there aren't many alternatives to C++.

