
Why do C++ folks make things so complicated? - ColinWright
http://www.johndcook.com/blog/2011/06/14/why-do-c-folks-make-things-so-complicated/
======
CJefferson
The biggest problem with C++ (in my opinion) is a lack of a good library
manager.

As installing C++ libraries is a pain, and testing them on a large range of
compilers is a pain too, the only library of note anyone ever uses is boost.

Most of Boost is a horrible templated mess. I consider myself fairly expert on
C++, have contributed code to both clang and g++, and worked on C++11. I still
don't use boost, and am slowly taking it out of projects which it has
infected.

Boost is interesting as seeing how the bounds of C++ can be pushed, but as a
library for day-to-day use it is horrible. It is just about usable if you
limit yourself to a few small pieces. For example at first glance
boost::spirit is a really nice parser library. However the error messages give
me shivers to this day and a parser I wrote using it takes over 1GB of memory
and 40 seconds to compile.

~~~
roel_v
Please tell what is wrong with libraries such a datetime, regex, filesystem,
bind, shared_ptr, string, test, uuid, just to name the ones I use regularly.
Also please tell what you would suggest as replacements, and why they do not
share the deficiencies the boost versions do according to you. It's easy to
hate on templates, and not is all perfect in C++ or boost, but boost is the
best thing to happen to C++ to make it easier to use, or rather to alleviate
some of the most annoying and unnecessary drawbacks of the language. I'm not
questioning your expertise, I'll take your word for the accomplishments you
mention - but your apparent disdain for it is, to put it mildly, lightly
substantiated and shows more signs of ideologically fueled hatred than of a
deep understanding of the negative sides of something that can only be
developed through much experience.

~~~
to3m
Sometimes, you can see the negatives straight away. No experience necessary! A
40 second compile time is a pretty big negative. I wouldn't even suggest this
is exaggeration; my experience with boost is not that wide-ranging, but what
experience I have does include waiting for programs to compile.

(Maybe experience is even the problem. A C++ programmer might suck up a 40
second round trip time, but I bet no PHP or Python programmer would!)

Large C++ projects already tend to suffer from monstrous compile and link
times. Anything that increases build times is inherently a bad idea. Iteration
time has been THE major issue on every project I've worked on. Sucks up man-
hours like nobody's business. All the other C++ junk... borderline irrelevant,
by comparison.

~~~
zvrba
Not to mention link times: templates generate HUGE mangled symbols, with
corresponding increase in memory and time as all those strings have to be
stored and string-compared.

I've long wondered about why doesn't any C++ compiler implement symbol
hashing? As in: replace symbol names with symbol hashes (SHA1) in the symbol
table, and emit an extra section that maps hashes back to mangled names.
Linker could do all of its work using hashes, and would map them back to
regular symbol names only when generating the final debug info file.

~~~
FooBarWidget
Some C++ implementations already implement symbol hashing.
<http://blogs.oracle.com/ali/entry/gnu_hash_elf_sections>

~~~
zvrba
This is an improvement of existing hashing scheme in ELF object files, and is
completely different from what I proposed.

~~~
FooBarWidget
I know, but it is hashing nonetheless. Doesn't it effectively achieve the same
goal that you're after, namely faster symbol lookup?

~~~
zvrba
It is not as fast as it could be. It is an implementation of ordinary hash
table, meaning that also a successful search requires comparing two strings
several kB long. What I propose is to reduce ALL symbols to their hashes (SHA1
is 20 bytes) and to "dehash" them only after linking has been done.

Collision in hashes is of only theoretical interest when you consider SHA1 or
SHA256.

------
pnathan
In my experience writing C++ as a hobbyist & minor professional work, it leads
to complexity for a couple reasons.

\- Lack of higher order functions generates boilerplate classes for fairly
simplistic closure-istic operations

\- Using templates with any sophistication infects gobblygooky templating
syntax around your codebase. Since templates are actually a really nifty
concept and worth using, this happens pretty quickly and now your codebase has
more angle brackets than braces. ;)

\- Inability to add syntactic abstraction means everything is written out, all
the time.

I spent a lot of time learning C++98. After I got exposed to other languages,
I don't think I'm going back to C++ without a good reason. There's too much
ceremony for too little gain. Arguably with sufficient blood, sweat, and tears
libraries can be written to make C++ do or fake what other languages do
easily, e.g., regex, closures or continuations.

I think that taking the dynamic language approach of C in the performance
parts and dynamic language for the rest is a better way to architect your
system. Or, select a dynamic language that compiles to native code. :-)

~~~
fauigerzigerk
_Inability to add syntactic abstraction means everything is written out, all
the time._

I disagree with that one. Of all popular languages, only Python and Ruby
(maybe C#) come anywhere close to the level of syntactic abstraction that C++
supports.

~~~
pnathan
When I say syntactic abstraction, I mean Lisp-style macros.

Python's decorators do a weaker version of the same thing.

------
makecheck
I will go as far as to say (from experience) that releasing a library in C++
to others is completely _foolish_ due to the major problems it can create when
design changes are inevitably needed. Other languages do APIs better.

C++ is useful for implementing the _guts_ of things. And when implementing,
having _your own_ library of shared C++ code is useful, as long as you
_completely_ control it and always compile it with your project from scratch
(a library of templates, for instance). The last thing you want is to link to
someone else's compiled C++ library because that's where the pain begins.

To expose a C++ implementation, use a plain C interface; the C application
binary interface works very well across compilers. If you feel it absolutely
necessary to expose something like the inheritance scheme of an object-
oriented design, you had better do it in a language like Objective-C that can
at least implement objects in a very forward-compatible way (or use tricks
like exposing pointer parameters in C functions).

~~~
asher
I agree. Also, the pure-C interface is easier to wrap from scripting
languages.

~~~
cbs
If you haven't heard of it before, swig (swig.org) is pretty nice for
generating code to bridge C and C++ code to a scripting language for you.

------
steve8918
I disagree that it has anything to do with the language.

For example, I just recently started using Boost. Holy smokes, it is
BEAUTIFUL, at least the parts that I've used. It just works. I've never worked
with a library where I look at the example, make a guess as to how it should
work, and it just works. On the other hand, the company I work at uses Boost
in a completely illegible, unmaintainable way. It has nothing to do with
Boost, it's whoever uses it.

To say a language such as C++ is responsible for overly complicated interfaces
is just plain dumb. It's not the language it's the implementer. I can take the
same $200,000 violin as Joshua Bell and make horrendous sounds from it. It
doesn't mean that the violin is a piece of crap, it just means that I have no
idea how to play a violin.

~~~
buff-a
I've met lots of people who code C++, and advocate C++.

I've met lots of people who code Java, Ruby, etc and advocate those.

I've met very few people who've shipped one product using C++ and another
using Java/whatever - but those who have? They advocate using C++ sparingly if
it all.

Bottom line: if you goal is to have beautiful classical music in the
background for your party, then you could hire Joshua Bell, you could spend
years trying to become Joshua Bell, or you could buy a fucking iPod and _move
on to the next problem_.

~~~
killedbydeath
I have shipped products in C++ and Java and would definitely advocate C++ over
Java in almost every situation. Java manages to be more verbose and less
powerful at the same time. Then again I currently use Python mostly, so I
guess I am using "whatever" but I do not think Java/whatever is a valid
category.

------
fab13n
Here's an idea: why don't we put distinctive marks at the boundaries between
Top C++ and Bottom C++? Say, square brackets. If the Top C++ superficial
syntax happens to be a little bit smalltalkish, we could call the resulting
language Objective C!

Kidding apart, one of the anti-patterns the most specific to C++ I've met is
inability to decide whether some code is high level or low level. C should
have been embedded in C++, with clear segregation marks, not extended/inflated
into C++.

------
mmphosis
_Apple’s Mac OS X, Adobe Illustrator, Facebook, Google’s Chrome browser, the
Apache MapReduce clustered data-processing architecture, Microsoft Windows 7
and Internet Explorer, Firefox, and MySQL — to name just a handful — are
written in part or in their entirety with C++._

The key phrases are "to name just a handful" and "written in part."

It's very simple because most of this handful of a particular type of software
are written in C, not C++.

~~~
buff-a
[http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-
mapr...](http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-
project/src/)

Hadoop is in C++? Those five files in the C++ directory?

------
shin_lao
C++ is an expert's language perfect for solving very difficult problems. Used
properly it leads to an extremely elegant, efficient and agile code.

Now there's not "one way" of doing things and anybody is doing it "it's own
way". There's probably more than ten C++ dialect.

When you're used to one dialect you tend to believe the other is
"complicated". When you're not used to generic programming or templates you
tend to think it's "over complicated" and "useless".

And if ever you mix the dialects, you end up pretty quickly with something
horrible.

------
tptacek
Nit: OS X is not written in C++. Small parts of it are, but most of xnu is C.
C is simple. C++ is not.

Having said that: TR1 regexes seem like an uncommonly simple C++ API.

------
frou_dh
The endless comments on that post arguing about C-vs-C++-vs-C#-vs-ObjC make me
want to jump in to a volcano. Those stories from the last few days about
reducing time spent reading the internet might be on to something.

~~~
mattgreenrocks
It's all bikeshedding, and thus should fail HN's test of interesting content.
Junior programmers obsess about this crap. I don't know why these discussions
continually pop up. It really makes HN look like /r/programming, and that
isn't saying much.

Of particular note are comments in the vein of, "I haven't used Language X
much, but it is terrible." I'm baffled why they're not called out for their
obvious lack of intellectual honesty.

~~~
jrockway
Why do you have to use something to know it's terrible?

~~~
mattgreenrocks
Because, all too often, those comments are not prefixed with, "I haven't used
Language X, but I hear that". Instead, they masquerade as comments by someone
with actual experience. The poster knows that if they were to add that
disclaimer to their statement, it would lower the credibility of what they're
saying.

And we all know you gotta be Right On The Internet, not intellectually honest.

------
jcfrei
I tend to think that applications developped in C++ are usually more complex
and hence you get the false notion that the complexity stems from the
language. While in fact you're just comparing apples to oranges.

------
lallysingh
Ignoring the Top C++ ideas, to answer the question of this article: C++ wants
too much (high abstraction with high efficiency in the general domain) with
too little to work with (a minimal type system, a minimal generics system).
Classic work from a committee -- it's easy to agree to lofty ideals, but
difficult to agree on how to get there.

So, everything built atop this doubly-pronged-mistake ends up paying the
price, in complexity.

~~~
lurker17
What does a committee have to do with it? Most of C++ was there when Bjarne
Stroustrup created the original versions himself.

~~~
qdog
Stroustrup apparently listened to a lot of people at Bell Labs while creating
c++, essentially creating it by committee. I think there is a quote by someone
about this, Rob Pike? Can't find it at the moment.

~~~
nosefrog
Are you talking about the quote ten paragraphs down?
<http://harmful.cat-v.org/software/c++/coders-at-work>

~~~
qdog
Ah yes, that was it, from Ken Thompson, thanks.

------
agentultra
C++ code isn't inherently complicated. The people who write C++ code might
make their programs unnecessarily complicated. I've read at least one program
that was written that way. A web application written over 12 years ago without
the aid of standard libraries or common sense. However, I've also read some
really great code in C++. It seems to me to be very polarizing because it lets
you do what you want without forcing any conventions on you, the programmer
who knows what they're doing.

I suspect the reason why people who make programs with C++ make those programs
unnecessarily complex may have more to do with their psychological makeup than
the limitations of the language (which I believe to be rather few).

------
cakoose
I think he's taking a widely-accepted idea -- that the C++ language is a
complicated language -- and making the unfounded leap that most C++ code is
just as complicated.

For starters, the standard C++ string type is reference-counted, something
that leans more toward convenience and simplicity than maximum performance.
Well-designed C++ libraries that don't need to push the performance envelope
are often pleasant to use.

Maybe the author wants things to be even simpler, but he's gotta provide
examples. Or at least describe what his ideal Top C++ would consist of. That's
the hard part. Simply saying "we should make a simple version of C++ that
still lets you do low-level stuff when you want" seems vacuous.

~~~
SamReidHughes
> For starters, the standard C++ string type is reference-counted,

The GNU implementation of it is reference counted. I don't think every
implementation is.

~~~
ramchip
Indeed, recent versions of VC++ don't use reference counting.

------
supar
I often hear these arguments about C++, but after having used C++ for almost
my entire career (and looking forward to use C++11) let me tell you why people
continue to use C++: because C++ is performant, and the alternatives don't
give you enough control over the internals.

Yes, C++ is incredibly complex. Inherently _much_ more complex than, say,
Haskell; due to the fact that C++ is far less consistent, has an hairy syntax,
and non-uniform libraries (a problem which is also shared by perl and ruby,
due to the language flexibility and rhetorical "best practices").

 _But_ C++ delivers! And while not better than Python, it still allows higher-
level programming than C, while attaining the same level of performance.

While you probably don't care that python 3 (a language I also love) is
overall roughly 10% less efficient than the old 2.7, I need to figure out how
to crunch a dataset which is doubling each month, while CPU power is not
increasing in frequency any more. While your favourite language du-jour still
needs to figure out how to do basic multithreading, I'm actually exploiting it
since _decades_ , including SSE and CUDA while I'm at it. Sure, the result is
not pretty, but it seems today that thrashing cycles "in the cloud" is not an
issue anymore.

Thank god I don't work in that industry.

------
dicroce
Early in C++'s existence, C++ took a lot of crap from C programmers regarding
performance. In those days, C programmers complained of the "overhead" of
virtual function calls... and the "bloat" of objects.. As a result, the C++
community became super focused on performance... Most of the features in C++
are completely opt in (I.E, if virtual functions are too expensive, you are
free to not use them and not pay any penalty)... This attitude bled into the
STL...

Another factor that complicates the STL is it's approach to generic
programming... In my opinion C++ took the purists approach (instead of the
pragmatic one)... So, std::list doesn't have a .sort() method... Instead, you
can use the sort algorithm on any container that implements the right kind of
iterators...

IMHO, C++ needs 2 standard libraries... One for purists, and one for
pragmatists... (and the pragmatists will use the STL to implement their
standard library, but the pragmatist::list will definitely just have a .sort()
method!)...

~~~
kstenerud
Thus the following quote:

"Whenever the C++ language designers had two competing ideas as to how they
should solve some problem, they said, "OK, we'll do them both". So the
language is too baroque for my taste." -- Donald E Knuth

------
sbmassey
There are some C++ libraries that are perhaps more complex than the
equivalents in other languages, but tr1::regex's are pretty much the same as
regexes in any other language, if you discount the static typing stuff.

------
yason
C++ is the engineer's wet dream vision of what C _could_ be.

C is the wise man's careful vision of what C _should_ be.

------
known
It is complicated because a _sophisticated C++ application_ is written by more
than one programmer.

------
chj
it is called object hell. we want to get things done, but they give us a lot
of objects.

------
radicalbyte
> Why do ____ folks make things so complicated.

The answer is often "job security" or, in the case of consultants "to maximise
billable hours".

------
moonboots
Top C++ sounds complicated to me.

------
zvrba
Why do we make things so complicated? Because C++ is a low-level abomination
pretending to be a high-level language. Let's start.

\- Allocators in the STL are a joke, so you can't use them for implementing
different memory models. So you end up implementing, e.g., linked lists from
scratch.

\- You can't "steal" underlying storage from a vector, which means you can't
use it as a simple memory pool. So you end up implementing a vector from
scratch.

\- size() of containers returns an unsigned type, which is a perpetual source
of code ugliness and cursing in may day-to-day programming. (The most trivial
example: make a backward loop through a vector. No, don't tell me to use
iterators -- index has also semantical meaning in my use-cases.)

\- There is static_cast, reinterpret_cast, dynamic_cast, const_cast, but no
cast which would actually check that what you're trying to do makes sense. (C
and C++ standards stipulate that casting from A to B is well-defined A is a
"prefix" of B. This could be extended to check for layout compatibility, so it
would be legal to cast a linearly triply-derived struct with 3 floats to a
float array with 3 elements. Technically, it's UB, but "it works in practice",
and that "it works" could have been formalized. The compiler would be allowed
to reject non-working cases.)

\- Writing flexible, generic (template) code is all nice in theory, but, in
practice, it goes against the idea of separate compilation, with corresponding
increased compilation times.

\- Debugging heavily templated code is a nightmare.

\- Writing templated code is arduous. Templates being turing-complete, we can
never expect as good IDE support as for Java and C#. (I toyed with some simple
Java programs in NetBeans and I almost cried when I had to back to my day-job
of writing C++. IntelliSense of Visual Studio, like "state of art" IDE for
C++, is CRAP compared to what you get from NetBeans/Eclipse for Java.) I like
more and more the idea of using a "restricted" language augmented with a
powerful IDE.

\- The idea of constructors establishing class invariants is all well and nice
until you have to deserialize an object graph with cycles. (For this you must
temporarily have an invalid object that is to be filled in later.)
Constructors/destructors make sense if you actually have to manage
_resources_.

\- etc, etc.

In short, C++ has a history of incorporating half-baked features into the
language and/or standard library. Things get complicated because it IS
complicated to get a half-baked feature to do what you actually need to
accomplish.

What half-baked features? I've already mentioned allocators and casting.

Then there's RTTI, whose implementation is complex, but I don't know whether
any serious project uses it for something more than dynamic_cast. (In reality,
you would like to have full reflection, but you have to implement it yourself.
Yes, it's complicated.)

When you try to implement reflection yourself, you will, almost invariably,
use offsetof at some point, which, technically, yields UB in most cases, but
also it WORKS in the most common cases (no MI, no virtual inheritance).

There is auto, there is declspec, but there is no complete type-deduction, so
you often have to spell out things twice to the compiler, even though it
already has all information it needs.

There is no structural polymorphism [this is related to lacking casts] --
you're supposed to write template code with corresponding bloat of object code
and other, above-mentioned downsides of templates.

iostreams are barely useful: when opening a stream fails, there is no
standard-defined way of finding out WHY it failed (non-existent file,
permission denied, etc.. This is a KEY feature for any program that interacts
with a human user.) In C, IO functions set the errno variable, but not C++
streams. If you're lucky, errno will be set by the underlying system call and
won't be changed further, but you can't count on that. Yet another fail (i.e.,
half-baked feature).

Another iostreams misfeature: overloaded operators << and >> : the program
code leads you to believe that things execute sequentially, where, in fact,
the code is converted to function calls with unspecified evaluation order of
arguments. So if f() has side-effects, you don't know what cout << f() << f()
will output.

==

Maybe the new C++ standard fixes some of the above issues, but I'm so
disappointed by the overviews of what's new, that I won't even bother
checking. Many things are just cosmetic, some are outright stupid (e.g., user-
defined literals), but fundamental problems of piled-up, half-baked features
remain.

------
seanp2k2
I don't know C++, but I know a few other langs and can figure stuff out
quickly. I was reading through Chromium sources yesterday trying to track down
the conditions that must be met for a specific error to be thrown. It was all
callback spaghetti and I gave up after tracing calls back through 10+ files.

~~~
abcd_f
This has little to do with C++.

------
ntkachov
I like to use the following flowchart when deciding if I'm going to be using
C++.

Do i need to do alot ----Yes-----> Java[script]

of string parsing?

    
    
           |
    
           No
    
           |
    
           v
    
          C++

