
C++ and the Culture of Complexity - thebear
http://blog.greaterthanzero.com/post/58482859780/c-and-the-culture-of-complexity
======
jandrewrogers
A lot of the nominal complexity of C++ is the result of the very precise
control it offers over software behavior. In many programming languages this
level of control is not even expressible. That extra level of control only
seems like unnecessary complexity until you are designing software systems
that require this level of control. At a minimum, precise control of memory
management is absolutely essential for things like servers and database
engines if performance matters at all.

That the author thinks C++ is competing with Go betrays a narrow perspective.
There are many important things you can do in C++ that are not possible in Go,
in part because of the features that make C++ "complex" that simpler languages
do not have. As an obvious example, the renaissance of C++ for high-
performance server systems is based in part on the fact that garbage
collectors are a major drag on performance for these kinds of codes.

Which is not to say that C++ is not excessively complex, just that the author
seems to lack an understanding of why some of that complexity is essential
functionality.

~~~
cmbaus
Personally I think the notion that C++ offers "precise control" as you call it
is overrated. For instance flexible memory allocation is touted as an
advantage, but in practice this is limited by the fact that there is only one
global implementation of new the operator.

Over the long term I think Go is going to offer a much more sane environment
for implementing high performance servers.

~~~
mpyne
C++ does allow overriding the new operator, actually.

It also allows for running _just_ the constructor in an area of already-
allocated memory, if you're particularly crazy.

With that said it's hard to argue that Go makes concurrency easier at this
point, which can certainly make it more useful for many of the types of
problems programmers are seeing today.

~~~
cmbaus
I realize this, but you can't provide multiple global implementations of new.

It is difficult to implement multiple allocation strategies in the same
application. In another time, I actually did quite a bit of work in this area:
[http://accu.org/index.php/articles/1308](http://accu.org/index.php/articles/1308)

~~~
pcwalton
You can just provide an allocate() static method and destroy() method on your
object that use placement new and call the destructor manually. Or don't and
just use placement new/manual destructor calling yourself.

Are you trying to argue that C++ programs can't use custom allocators because
of language restrictions? That's demonstrably false; Gecko and WebKit, just to
name a couple of C++ codebases I'm relatively familiar with, use custom
allocators everywhere.

~~~
cmbaus
Fair enough. My point was poorly made, and truthfully it has been along time
since I've done significant C++ work. But it is difficult for the users of
libraries like the STL to mix and match their allocation strategies, so for
all practical purposes, most applications end up using the default
implementation, or a single override of global new.

~~~
coliveira
Actually if you may create a policy for a particular type by implementing
operator new at the class level. I think you're not well informed, because C++
is the language that gives you the most flexibility to design memory
management schemes.

------
PommeDeTerre
C++, Java and JavaScript each have their own different kinds of complexities.

The complexities of C++ almost always arise out of the extremely high degree
of power and flexibility it offers programmers.

The complexities of Java end up having to do with hyper-"architected" class
libraries, rife with excessively-used design patterns to the point of being
incomprehensible.

JavaScript's complexity arises due to core functionality that's missing (such
as proper class-based OO, namespaces, and proper support for modularity), or
core functionality that's limited in practice (like it's prototype-based OO),
or core functionality that's unjustifiably broken (its comparison operators,
semicolon insertion, its scoping, its type system, its awful standard library,
among others).

Out of those three, JavaScript's complexities are by far the worse. The flaws
are outright stupid to being with, and there's nothing that can really be done
to avoid them in many cases. At least Java programmers can choose not to
create and use bloated class hierarchies, for instance. And at least C++'s
complexity offers superbly powerful features and excellent performance, and at
least it's understandable how and why this complexity thus arises.

~~~
rayiner
C++'s complexity does not arise from its power. With the exception of
templates, C is just as powerful but far more orthogonal and simple.

E.g. the difference between references and pointers. E.g. the phenomenally
baroque template syntax. E.g. phenomenally complex rules for multiple
inheritance. Slicing problem. Syntax so hard to parse only a couple do it
right. Lots of features that just don't carry their weight (operator
overloading).

~~~
pcwalton
> Lots of features that just don't carry their weight (operator overloading).

Operator overloading is crucial for things like graphics and
bignums—basically, heavy math operations over anything that isn't a primitive.

~~~
rayiner
Its a trick pony. I don't think that use is enough to carry its weight. Also,
abusing it immediately in the streams library just encouraged people to find
elaborate nonsensical uses for it.

~~~
mpyne
Operator overloading is very useful in the context of generic code though
(through templates).

I've programmed C++ for probably more than a decade now and I've been bitten
by many of its features at some point, but operator overloading would rank
right near the bottom of my burn list.

It _can_ be abused, that's for sure, but so can many C features.

------
wheaties
Being a recovering C++ programmer who wrote some very clever code while
younger and very dumb code while older, if you think Java gets out of your way
perhaps you should try Scala or Clojure. Talk about getting out of the way,
these LAn guages are something of a wonderment. Every day I get to code in
them is a good day. It's true, you won't have the "power" of C++ but if you
need that there's C.

~~~
thebear
Author of blog post here: I haven't found the time to do much with Scala or
Clojure, but my impression so far agrees with what you say. Thanks for
reminding me: I need to seriously try out Scala _and_ Clojure!

------
dkirkman
To be fair, the c++ programmer can also use reference semantics via pointers.
Granted, garbage collection is not built into the language, but if desired, we
can always write java-style code by using pointers for everything and using
the Boehm collector. I don't know why we don't do this more often, most c++
codebases seem to have large sections that would benefit from such a style.

But when we want to use value semantics, for whatever reason, the more
complicated value copy is, to some extent, just intrinsically complicated. In
java, Object.clone basically has all of the same problems -- you sort of know
what you'd like it to do for any given object in any given context, but you've
got to read code to figure out what is actually going to happen.

~~~
pcwalton
> I don't know why we don't do this more often, most c++ codebases seem to
> have large sections that would benefit from such a style.

Because you will sacrifice performance over Java's GC. For maximum performance
you really want precise garbage collection on both stack and heap, with
generational concurrent operation and a two space copying collector in the
nursery. Boehm can't provide this, because the language is not designed for
GC.

~~~
adamnemecek
> you really want precise garbage collection on both stack and heap

This might be a dumb question but what run-times have a garbage collected
stack? I Googled around but did not really find anything.

~~~
pcwalton
I don't mean a garbage collected stack per se (though since you asked, SML/NJ
has this, as do several Schemes). What I mean is that precise stack maps or
register tagging is used so that the roots can precisely be found on the
stack.

------
pcunite
Given what we know today, yes a new language is warranted.

The reason I've stuck with C/C++ is because everything I've ever written still
works. Meanwhile my friends are playing with new languages every year (and all
the books, classes, and conferences to go along with them). All the new
syntax's seemed driven by corporations vying for mindshare ( _money_ ), not
the betterment of our industry.

Give us a _real_ alternative that is community driven and standardized. It
needs to compile everywhere, have the option of a great IDE, and have
libraries that make sense. We don't need another cute or toy language
(JavaScript's 10 day incubation that I'm stuck living with now). Until then
... C++ is what we have.

~~~
PommeDeTerre
Rust has the most potential at being a true successor to C++. But it's not
very usable at the moment (it suffers from far too much change within the
language and standard libraries), and it will still take a lot of work before
it is a production-grade language.

~~~
thebear
Author of blog post here: Interesting that you say that. I came really close
to saying in the blog post that Rust could be the alternative to C++ that I am
looking for. But then I decided that I know way too little about Rust at this
point to make that statement.

~~~
mpyne
The one thing with Rust is that it seems to me to also offer so much fine
control on memory ownership that it would start to develop its own set of
"gotcha"s.

With that said I'm looking forward to seeing progress on the language as I
think we've been needing a systems programming language where you can express
ownership semantics as part of the language itself, and have the compiler
check those for you.

------
alextingle
Totally agree. C++11 was a huge disappointment to me - rather than taking to
opportunity to make changes that would help attract new C++ programmers, the
committee decided to allow the "C++ nerds" to pile on even more complexity to
their already overwrought libraries ( _cough_ boost _cough_ ).

~~~
PommeDeTerre
C++ is a tool for power users, not a popularity contest.

Changes to the language should not be done just to attract more users. This is
especially true if these new users would be today's PHP, JavaScript and Ruby
users. The C++ community is much better off without these kinds of
programmers.

It's much better for people to use C++ when they realize that they need the
powerful functionality it offers, rather than dumbing down C++ in a way
that'll make it attractive to less-skilled developers.

~~~
betterunix
"It's much better for people to use C++ when they realize that they need the
powerful functionality it offers"

Relevant anecdote: I know a number of C++ programmers who said they would use
Haskell / Python / etc. to "prototype" a system, then switch to C++ when they
needed what C++ has to offer. None of them made the switch back to C++ and
their "prototypes" became finished products.

~~~
sehrope
> None of them made the switch back to C++ and their "prototypes" became
> finished products.

This is because the _vast_ majority of the time people's claims of performance
requirements are complete BS. If you're writing true system software (an OS
kernel, a database, an MQ system, etc) then shaving microseconds _is_ going to
matter because 10s, 100s, 1000s or even more applications built atop or using
your code will be leveraging the minor gains you are creating. If you're
building "Misc App X" then it's probably not going to matter.

~~~
thebear
Author of blog post here: That has been my experience as well. People tend to
overestimate their performance requirements. Then, in the name of improving
performance, they do all kinds of things that bring down their productivity
and increase the complexity of their code (choosing C++ as the programming
language is one of those things), but they never verify if any of those things
really made enough of a difference, if any, to create value.

Another thing I noticed is that of those people who do have serious
performance requirements (OS kernel etc.), many choose C over C++. We all know
what the most famous example is. I have no experience in this area. I wonder
if there is any data on the use of C vs. C++ vs. other languages like Go in
that realm.

------
claystu
That quote by Bjarne Stroustrup: "I--and my colleagues--needed a language that
could express program organization as could be done in Simula...but also write
efficient low-level code, as could be done in C."

in _Masterminds of Programming_ , p.2 (Interview with Bjarne Stroustrup)
O'Reilly Media, Inc. (2009)

A truly great read...

~~~
thebear
Author of blog post here: Thanks! I'll add that to the blog post.

------
zwieback
This is one of those articles that really resonated with me although I feel a
little uncomfortable admitting it. I think C++ is a great language but what
Becker says rings true to me. Of course I've always been of the "safe-subset"
mindset, e.g. the project and team should dictate how fancy your C++ should be
allowed to get.

------
comex
I'd like to see a language with the power of C++ without some of its
complexity. As noted elsewhere in the thread [1], there are a lot of features
that just aren't necessary for the combination of performance and
expressiveness C++ offers; on the other hand, while C is simple and can
usually offer equal or better performance, its lack of templates hurts its
expressiveness badly.

But Java or JavaScript? If your performance needs are satisfied by those
languages, great, but you're not the target audience - not today, anyway, now
that those languages exist and are reasonably fast. But if not, good luck
trying to beat the JVM into doing what you want. [2]

[1]
[https://news.ycombinator.com/item?id=6266633](https://news.ycombinator.com/item?id=6266633)

[2]
[http://marc.info/?l=git&m=124111702609723](http://marc.info/?l=git&m=124111702609723)

~~~
javert
If C++ was originally "C with classes," has anyone invented a "C with
templates"? Might not be a bad idea.

~~~
vilya
I got the impression that's what the Clay language [1] was aiming for, but
progress on it seems to have stopped around a year ago.

[1] [http://claylabs.com/clay/](http://claylabs.com/clay/)

------
nicholassmith
C++ is hard and complicated, but it's very useful if you're strict with it. I
agree with the authors post though, there's a lot of inherent complexity
that's non-trivial to solve and often leads developers to try and be clever
rather than building strong software.

------
ExpiredLink
The problem with C++ isn't complexity but _unnecessary_ complexity. As the
author points out this is a cultural and not an 'inherent' problem (people who
claim that a language like C++ _must_ be complex are simply wrong).

C++ did not start out as complex language, though. Quite the contrary. Just
take a look at early C++ books. The turning point happened in 1995 when
Stroustrup switched the C++ paradigm from object-oriented to the functional
inspired 'STL paradigm' (remember 'multi-paradigm'?). Afterwards a clique of
'Boosters' (nomen est omen) took over the language development and bloated C++
to the current mess. In evolutionary terms: C++, a versatile mammal that
developed into a dinosaur.

------
swinglock
> Trying to impress people with your code rather than with your software is a
> sign of immaturity and bad engineering.

That depends on what you think is impressive. A project that has clear and
simple code is impressive, in any way needlessly complex and difficult to
understand code is not.

~~~
thebear
Author of blog post here: Thanks, good point! What I meant was, "Trying to
impress with the _complexity_ of your code..." I'll change that in the blog
post.

------
betterunix
"Few people would disagree that assignment between variables is part of the
design of a language"

Perhaps so, but those that do disagree might be worth listening to:

[https://en.wikipedia.org/wiki/John_Backus](https://en.wikipedia.org/wiki/John_Backus)

------
kartoffelsack
the wow effect in c++ 'yeah i can do this cool stuff i read about in another
language also in in c++. i just have to use this fancy lib and its really cool
what you can reach with templates.' i foud always stunning. anyway it is no
good for efficiency - but having worked with c++ for some years makes you vety
efficient in more simple languages. i ser following drawbacks of c++ - the
default is very often not what you should do. this is the price for backwards
compatibility this makes it hard for the novice but you get used to. - the
incredible long build times esp when working with modern libs. how many hours
did i spend waiting for the compiler and how many for optimizing ny
precompiled headers. this is really a produxtivity killer. its has also
historical reasons but i dont understand why no proper module system gets
depeloped - the lack of support for runtime errors. for 7 years i have not
seen a crashing java program without giving me a hint where it crashed. and
actually i have seen far less total crashes. in c++ you do one small thing
wrong and the whole program ends with an abnormal program termination and you
dont have any clue what happened.

------
kartoffelsack
the wow effect in c++ 'yeah i can do this cool stuff i read about in another
language also in in c++. i just have to use this fancy lib and its really cool
what you can reach with templates.' i foud always stunning. anyway it is no
good for efficiency - but having worked with c++ for some years makes you vety
efficient in more simple languages.

i ser following drawbacks of c++ \- the default is very often not what you
should do. this is the price for backwards compatibility this makes it hard
for the novice but you get used to. \- the incredible long build times esp
when working with modern libs. how many hours did i spend waiting for the
compiler and how many for optimizing ny precompiled headers. this is really a
produxtivity killer. its has also historical reasons but i dont understand why
no proper module system gets depeloped \- the lack of support for runtime
errors. for 7 years i have not seen a crashing java program without giving me
a hint where it crashed. and actually i have seen far less total crashes. in
c++ you do one small thing wrong and the whole program ends with an abnormal
program termination and you dont have any clue what happened.

