C++11 Makes Competitors Go Rusty
nerds-central.blogspot.comYour freaking enormous ball of mud accreted some more mud. Quelle surprise. It's probably doing it by sheer gravitational attraction at this point. I do not think that removes the need for languages that have the capabilities of C++, yet aren't freaking enormous balls of mud.
The reader may mentally replace my use of the word "freaking" with other choice terms at his or her discretion.
I agree. I think people who know C++ and people who do not know C++ will have very different attitudes toward the evolution of C++. I sunk a lot of effort into C++ when it was the best game in town for a lot of things, so I'm excited to see one of the sharpest tools in my toolbox get a little sharper. If you must write C++ code (or C code, since it's easier to write C++ instead) then by all means you should learn C++ in all its gory mud-ballness, and you will have an extremely powerful weapon at your disposal which is much easier and safer to wield than you might imagine. On the other hand, I think anyone who doesn't already know C++ should avoid the investment of learning it if possible, and we should welcome new languages that relieve more and more people of that burden.
> anyone who doesn't already know C++ should avoid the investment of learning it
ACK. I know many languages, and my advice after using C++ for several years is: Don't dare try to do everything in C++. Use C++ only when it is absolutely necessary.
Just compare this C++ code
http://shootout.alioth.debian.org/u32/program.php?test=regex...
with this equivalent Javascript code to understand immediately what I mean:
http://shootout.alioth.debian.org/u32/benchmark.php?test=reg...
It's funny that this V8 code runs even 4.5 times faster (!) than C++ :)
http://shootout.alioth.debian.org/u32/performance.php?test=r...
Any useful language is a freaking enormous ball of mud. Bjarne said: there are only two kinds of languages - the ones people complain about and the ones nobody uses.
I can not think of a cognitively bigger language than C++. And I mean language, not library set or anything like that, but literally, what the syntactic constructs are, how they are defined, and in particular how they end up interacting with each other. I often wonder how many of the C++ defenders could actually answer detailed questions about it, or how much of the code they write would actually deeply, deeply surprise them with what memory allocation bugs are lurking, how much indirection there really is, or how many implicit copies of things they are making if they really took the time to step through the assembly language version. Or how many of them could bang out a decently accurate summary of the new official memory model, let alone how it might interact with all of the other features of C++. Or for real bonus points, successfully use it without introducing enormous numbers of things that are, technically, errors, but it so happens you never run into them at runtime.
Non-zero, I'm sure, but I bet single-digit percentages, tops. Except that last one, which I'd put money on sub-1%.
What are the odds that C++, as a fairly extreme outlier, is actually closer to optimal for the general purpose tasks it is used for than all the other languages?
You can replace C++ with almost any other mainstream language in the above paragraph and it would still hold true. Problem is, contemporary general-purpose languages are used for such a wide range of different tasks that it is simply impossible for them not to be complex (syntactically or in terms of runtime envoronment). And yes you can hide complexity behind abstractions (which our programming languages successfully do), but you cannot really eliminate it. And despite all that I see more real-world applications written in "horrible" languages like C++ or Java than in "elegant" languages like Common Lisp.
I can write Java code that will not surprise me with unexpected copies, contain huge memory problems (GC does have edge cases, but if you throw that in I will throw in "non-trivial memory management in C++ when 'just use a smart pointer' doesn't work" and you don't come out ahead at all), or surprise me greatly with the memory model. It doesn't have a huge syntax, and the language doesn't get 50% bigger on every release of the syntax. Many Java programmers can answer questions that go quite deep into how Java works.
I don't like or use Java, and it isn't perfect by any means. My point is just how far I didn't have to go down the list of "mainstream languages" before your claim is completely false. C++ is an outlier.
C also has the memory leaking issue, but the rest is false as well. Though in the memory model case it's by virtue of not having one.
And that's sticking with a very generous-for-you interpretation of "mainstream". If I'm allowed to dip down to Python or something you're even worse off.
All I can say is, I can write C++ code that will not surprise me with unexpected copies, contain huge memory problems, or surprise me greatly with the memory model.Stop whining and learn to use your tools, goddamit.
Stroustrup is right, but that doesn't prove your point. Every language will have detractors, but not every language will be the target of every particular complaint. Lua, for example, is a useful language and it has largely avoided being a ball of mud.
Naturally, that minimalism brings its own set of issues and complaints. But the point is, you don't need to be as much of a ball of mud as C++ in order to be useful or successful. I think a lot of language partisans, and C++ partisans in particular, point to Stroustrup's quote as an excuse for their language's warts. It's true that no language can ever be perfect, but that doesn't mean that all complaints are without merit and unworthy of attention and consideration.
I can't remember the source, but I'm sure I read somewhere that programming languages are either too large or too small...
I (shrug) enjoy programming in C++11 and like many concepts in it.
However, there are concepts in Go and Rust that are salient and stand on their own: typeclasses in Go and Rust (concepts, unfortunately, were left out of C++11), rust making std::unique_ptr<> a language feature and support for pattern matching, etc...
While I like support for atomics, memory model, etc.. in C++11, concurrency is still a library in C++. Go and Rust take different approaches to concurrency, but they do make it a _language_ feature which is substantially different.
In short, I hate to bible-thump Paul Graham's article, but this article does remind me of the "blub paradox".
tl;dr I like C++11, but I am glad there are other options (most importantly, Go, and Rust) being developed for userland systems programming.
I'd like to note that rust does allow mutable shared state, but just in an "unsafe" context, since it is in fact, unsafe.
Rust has typeclasses as well.
Edited appropriately. Please excuse my ignorance, then. I've only recent began looking at Rust, but I've been playing with Go for some time now. Will have to spend more time with Rust (if only there were more than 24 hours in a day...)
So, just to fan the flames a bit...
About half of his points are general gripes about software development, regardless of language(s): license infections, learning new languages, writing languages with the wrong idioms, runtime versioning issues, wah wah wah this all reads like somebody throwing up arguments just to try and distract readers.
His complaint (read:strawman) about interoperability and performance is really misleading. His 'Compatibility' section is not unfair, but all of those problems are faced by programmers dealing with system libraries anyways. Tell me more about the C++ bindings to C libraries and how they are never used in production.
His complaint about 'Performance' is similar FUD. Jesus, dude--if you agree on a calling convention, I can probably get my Brainfuck program to compile and interop with your C library. The computer really doesn't give two shits what language caused the stack pointer to move--it doesn't matter. This isn't a valid complaint.
His lambda is dumb. He didn't do anything there that couldn't have been done with a function pointer, C-style. If he was trying to show why C++11 lambdas are cool, he failed.
(and his code looked like garbage, as others here have mentioned... elegant my ass. No comments, ugly use of operators, namespacing--beautiful C++ this ain't.)
EDIT: Found this, same author I think ( http://nerds-central.blogspot.com/2012/01/sql-failed-experim... ). SQL is a distraction--quick, somebody warn Oracle that they'll be out of business!
Maybe the poor person is just getting lonely in that ivory tower?
Ironically his code sample makes me think we need a new language right away.
Of course C++ can do what Go and Rust do, C++ can do everything, but that is the problem with it. C++ tries to do everything and it leaves it not being very good at nearly anything. Also, C++ code-bases are all using different subsets of functionality. It makes becoming a product commiter to a code-base to longer than it should.
A couple of nitpicks:
C++/Tr1 has also solved many of the same problems without needing a new compiler
Not true. While many of the boost/tr1/c++0x features are introduced via new headers, there are many compiler-level changes, and that's why you need to use the latest versions of clang/g++/msvc/icc to take advantage of them. Things like r-value references just can't be done without a "new" compiler.
My other nitpick is his code sample: I've been write C++ for years but I must say his code sample made my eyes bleed. It's rather far from being demonstrative proof that C++ is elegant and need not be replaced. He should have just imported all the namespaces and been done with it, for starters, in this trivial sample.
I wonder if you are confusing TR1 (which came out several years ago), and C++11.
TR1 was designed to not need compiler extensions (although some parts of type_traits, that AFAIK no-one ever used in the TR1 days, could be improved with compiler support). TR1 added regex and tuple among others. It certainly didn't have rvalue references.
C++11 is the new big standard, which certainly requires large amounts of compiler support.
No, but I suspect the author of TFA is/has. That would explain the inconsistencies throughout his post.
I like and use C++. It fits my requirements of allowing high performance but still having rich abstractions. I also like most of the additions in C++11, and I look forward to using them.
But, there is a valid argument for using a newer language that has nothing to do with the language itself: the ancient include, compile and link process. Having to do the #ifndef/#define/#endif dance in every header file I write is a reminder of this fact. That hack exists because 40 years ago, there was no concept of package management. I feel the same way when I get linker errors that require me to unmangle my class names to figure out what's visible where.
> Having to do the #ifndef/#define/#endif dance in every header file I write
I'm just using "#pragma once" in my current hobby C++ project. I understand pragmas are living in sin, but is there any reason I shouldn't use them?
#pragma once aside, I agree that not having to worry about writing and including headers at all is a significant improvement of Go over C++.
It's not part of the C++ standard, so you're relying on a compiler extension. In theory, your code could blowup if you tried a different compiler, but in practice, most compilers you would use implement it. In general, pragmas are for compiler extensions - that is, things not defined in the language spec.
gcc 3.x had #pragma once bugs related to symbolic links. MSVC had bugs related to filenames that only differed by case. Modern gcc and MSVC can recognize and optimize for the #include guard pattern. Many benchmarks show no build time improvement of traditional #include guards vs #pragma once.
I some one benchmark where the developer #included all his headers and source files into a single .cpp file. Compiling this single .cpp file was about 50x faster than a traditional build! <:) Of course, you will likely have name and dependency conflicts.
I wouldn't use "#pragma once", but it's also a straightforward thing to change later. If that turns out to be the only thing you need to refactor away from later as the project evolves, you're doing great.
Not really anymore, it's supported on most compilers these days. But that's only been the case as of pretty recent.
The same could probably not be said if you were writing C instead of C++.
I find the concept of a C++ programmer using the ABI as a bullet-point against switching to a different language highly ironic.
Compatibility: The new language will have to talk with older languages. Types will have to be translated; memory models will need to be aligned and compilers will need to 'play nice' together. This is not just as the compiled object level but at the ABI level during linking etc. I've spent more time solving issues with memory models in C++ than I have in any other language because C++ has no ABI - I've had patches to MSVC change the memory layout of objects and cause breakage which is just as bad as you get with any sort of language interop scenario.
Performance: This new language is super fast. Great, but it will have to work with existing systems. The interface between the two will slow stuff down a lot... Seeing as C++ has no ABI, there's no non-hacky way to provide a C++ binary shared library that doesn't end up using a very small subset of C++ (for example, no STL, since it's all templated, meaning the code your compiler generates won't interoperate with the code the client's compiler), which means people end up wrapping their C++ code with C APIs.
Build: ... #include is a broken piece of legacy that everyone will be happy to see disappear - give us real modules instead of a compilation model which pastes file contents inside other files. Also, C++ compile times are ridiculously long compared to a modern CFG-based language (that's disregarding the fact that compilers often disagree as to what's valid code because of the extremely complicated syntax of the language).
Debugging: ... Debugging modern code that uses shared_ptr, bind, etc. is such a massive pain in the ass because you end up mixing the code you care about with those plumbing details - "step into " becomes useless. Add the fact that there is no ABI and you find yourself unable to introspect objects at runtime when compiled in release mode (where all the nasty memory issues tend to show up)
Team Training: ... C++ is, as I've been ranting, complicated. I've been using it for a long time, and there's still no language in which I fear making subtle mistakes that'll cause hard-to-diagnose bugs (for example, exceptions are often treated as an anti-pattern because it's so hard not to make such mistakes using them)
Team Embedded Knowledge: ... This is a valid point. I don't think it's worth the price you pay for using C++...
[Ecosystem complaints - tooling, licensing, lifespan] Beyond the fact that tooling for managed languages is often superior to C++ (because of the better-controlled memory layout and execution model), these are valid points.
Startup And Shut-down Sub-Systems: ... This is also broken in C++ - in what order are static objects initialized (definition order inside a cpp file, file sequences are random)? What happens if one wants to refer to another? I know these are solvable issues, but every single one of them requires thought and effort on the programmer's side, and these aren't the sort of issues that a programmer should be wasting his time on.
Paradigm Contamination: ... Yes, writing in a language and writing idiomatically in a language are two different things, but modern, idiomatic C++ is both something I've seen few people who know (compared to out-dated and dangerous practices), and it still requires more effort to keep in mind than, say, writing idiomatic python, or C#, or java.
Brain Strain (the bilingual problem): ... This isn't really an argument - it's speculation. I could say that perhaps the fact that C++ is so varied that different subsets of it end up looking like different languages, and all of them with more details you have to keep in mind to make sure you aren't breaking stuff subtly. Also, being bilingual also provides cognitive advantages, so even that flawed analogy might not be proving the point.
Let us think about the big ideas behind Go: [snip] Well, one can write simple clean C++ and use share_ptr. Just because C++ can be super complex does not mean it has to be. Unless, say, you're writing a DLL (another fun fact: not only can your API not have STL, exceptions also can't cross DLL boundaries), or you're using DLLs written by other poor souls who were consigned to writing DLLs with a C++ API.
This is not to say that C++ has no place in software development (I use it daily at work), but I'm of the opinion that unless you have a really good reason, avoid it like the plague. New languages taking over more niches C++ used to occupy is a good trend.
As a finishing note, one of my favorite articles on the subject of complexity in programming: http://www.joelonsoftware.com/items/2009/09/23.html
I'd like to upvote twice, but it wouldn't let me.
So it's cruel, but I usually secretly assume that people who keenly advocate C++ are just poseurs.
Anybody who has actually gone through the whole process of making a program in C++ and fixing enough of the bugs in it that somebody can put it in a box and sell it in the shops, is appropriately circumspect in their recommendations, because they know just how appallingly awful it can get.
So awful, that you'd give up on exceptions, DLLs, new & delete, templates, STL, auto-registering static globals, and all that kind of stuff - because it's actually EASIER to give up all those time-saving modern conveniences, than it is to pick up the pieces after they've been overused.
But nobody believes it until it's happened to them. It just sounds too implausible...
Amen! There are good reasons why Google's [1] and Mozilla's [2] C++ style guides frown on C++ features like exceptions, RTTI, iostreams, and static objects.
I read an anecdote that Bill Joy has a "copy of Bjarne Stroustrup's The C++ Programming Language in which he's highlighted all the sections that Java programmers don't need to concern themselves with." I wonder what a C++-compatible subset language would look like if someone just deleted code from a C++ grammar. Rather than writing style guides and lint scripts, just whittle down a C++ compiler's front-end. :)
[1] https://google-styleguide.googlecode.com/svn/trunk/cppguide....
[2] https://developer.mozilla.org/index.php?title=en/C%2B%2B_Por...
Sure C++ can do what Go and Rust do. In fact any language that is turing complete can do anything that any other turing complete language can do. It just matters how easy to do it and how the syntax is. It's all about warts, and C++ has a lot of them.
Is it just me, or could the author know only Go and Rust from their Wikipedia entries?
It's not just you. This made me laugh: "Let us think about the big ideas behind Go: It is simple, clean and has garbage collection." Enough said, really!
> In fact any language that is turing complete can do anything that any other turing complete language can do.
False. Or how exactly are you surfing the web with your Turing machine?
Let us think about the big ideas behind Go: It is simple, clean and has garbage collection.
That's quite a bit of an oversimplification. Goroutines and channels are two big ideas in Go, and the author pretty much ignored those completely.
As soon as he said "both Google and Mozilla have been playing the 'new object oriented native language' game recently", I stopped reading.
If you aren't sufficiently familiar with either language to know that neither of them is particularly object oriented, at least in the traditional sense, then you probably shouldn't be writing about them.
I agree that this paragraph is badly worded but the rest of the article hardly deals with anything related. There are some valid issues here that have nothing to do with the programming paradigm advocated and supported by either language.
C++ is great if used with care, the problem is that it has too many features and many things are quite braindead. Features are hardly ever removed (I like the Python approach better) But for complex, high performance applications it is still the best choice.
How many people here who complain about the language being too complicated have actually been harmed by the presence of features in the language? If you want an advanced programming language, it's going to be complicated. Without garbage collection, it will be even more complicated. Almost every feature that exists in C++ exists for a reason, and every one that was added or removed in C++11 was added or removed for good reasons.
If you want a less complicated language than C++11, other than some low-hanging white noise inherited from C, you'll probably have to give up safety, convenience, performance, or exceptions.
> have actually been harmed by the presence of features in the language
I am harmed routinely by too many features. I've been coding C++ for 11 years and I still end up scratching my head when I end up in foreign territory. Even his code at the end of the article which I think is supposed to be illustrating some kind of simplicity looks like a giant hairball of mess to me. I've ended up devolving to using a small subset of C++ features in my code which I know inside out and is sufficient for my needs. Others all seem to do the same but they arrive at a different subset. Java on the other hand seems to be so feature deprived and simplistic (minus generics, but they are almost an anti-feature) that no matter whose code I look at it is extremely obvious what is going on.
I spent almost as much time learning advanced C++ as I did unlearning it and going back to KISS. Even then, I still had to deal with code from people who were stuck in the advanced stage.
Can I just trade in my exceptions for Maybe or Either? It's already possible to do both of these things, the trouble is that I have to use other people's code that uses exceptions.
Except the C++ dragon rears its head. How do you build an intelligent Maybe or Either type in C++? Should they be value types containing unions? You can’t use “non-trivial” types in unions till C++11, and a lot of people haven’t yet upgraded. Referential types with dynamic allocation? How do you transfer ownership? Are “Left” and “Right” subtypes of “Either”? It’s ridiculous.
The choices are clear for every situation you describe.
To you, to me, but not to most C++ users. Yeah, these types should be in a library, but that’s not the point. A programmer shouldn’t have to be on par with the Boost writers to make something this conceptually simple. I’ve used C++ as my primary language for years and only now can I speak with authority on the finer points of the language. It’s quite powerful, but so unpleasant.
No offense, but have you spent much time with Go or Rust? In most cases Go's performance difference isn't extremely divergent from C++'s and it preserves safety and enhances convenience, exceptions and adds concurrency.
Go afaict does more than preserve safety, it improves it! And it enhances convenience. Concurrency in C++ works just fine, though.
Last I heard the Go compiler was generating code 6x or more slower than comparable C++ code. Is that not still true?
You heard wrong: http://blog.golang.org/2011/06/profiling-go-programs.html
The graphviz / svg output from the profiler shown there is very nice. Does something similar exist for other languages? I particularly like the scaling of the node size by the appropriate value (CPU time, memory use, etc).
Go's pprof is based on the C-based one: http://code.google.com/p/gperftools/
I do systems programming and I use C++ a lot. It's perfect for that. Anyone who does systems or embedded stuff will tell you how wonderful C++ is over the alternatives.
I hate to be "that guy", but for someones sake, fix the site on ipads. Not only it tells you you're using an incompatibble browser (a blast from IE past), then it swirtches to iPad specific (????) non-zoomable fixed layout, which makes it pain to read.
Really, how can a tech person think this is a good idea of publishing content? Please fix it.
It all boils down to whether you're starting a new project/binary. If you are, go with the new and leave all the backwards-compatible crap behind. If you aren't, then this article will speak to you. I also wouldn't want to be in your shoes.
I have fun when I write code with Go. I love the syntax, type inference and standard libraries. I wrote a transcoding video http server with html frontend in like a hundred lines of code and it doesn't make my eyes bleed. I don't think Go needs to replace C++ but I certainly prefer it. I think there are tons of uses for C++ still obviously (least of which is Go's GC-nature), but I don't think C++11 makes redundant the space that Go can occupy.
I know it's personal preference (but frankly, so is the article's position) but that C++11 code looks terrifying to me, I'm still guessing at what several of the pieces of code do. A python programmer looked at my go-code and very easily deduced what it was doing and made good suggestions immediately.
edit: s/VM/GC
Just a small nit, Go does not use a VM. It's compiled to machine code.
You're absolutely right, I thought GC and wrote VM.
Go is implemented in C and C++[1]. I often tell people that Tcl is a C library with a flexible configuration file. But comparing compactness of code when all you are really doing is invoking C is misleading.
[1] http://stackoverflow.com/questions/3327676/what-language-is-...
If only it supported a platform my clients actually use.
I assume you mean Windows?
http://code.google.com/p/go-wiki/wiki/WindowsSupport
Builds track weekly and with Go 1 coming up, it's a moot issue anyhow.
I was more thinking iOS and Android. Though I haven't investigated weather or not it could use the NDK.
Ah, my mistake. I know that you can build ARM binaries with Go, you ought to be able to invoke those from the NDK.
/r/golang had a link to this a while back, re: Go on iOS: https://groups.google.com/group/golang-dev/browse_thread/thr...
Looks like the iOS port requires a bit of work on cgo support for arm/linux before a proper iOS app can be made. Without the cgo shim it seems the app can't run more than 10 seconds, though the benchmarks are quite good.
Thanks I hadn't realized they had gotten so far.