This decade old article describes an ancient and obsolete language (C++03 probably though some of the text suggests it might be C++98). It's not worth reading in 2020.<p>Modern C++ is a very different language though it can still almost completely interoperate with quite old code. C++11 and C++14 already addressed most of the things brought up, and contemporary C++ (obviously most code is not in it yet) even supports generic template functions with a straightforward syntax (i.e. use auto instead of <..>).
I recently picked up a C++ codebase I wrote maybe 30% myself and which was last touched in 2013. It's a plug-in for a DCC app.
The 3rd party API it communicates with was changed so refactoring was inevitable.<p>Before I started refactoring I decided to make everything 'less ugly' by moving it to C++17. Which would also help me get back into the code, after eight years.<p>I spent two days on this. Then I decided: fuck it. I will RIIR™.[1]<p>It will mean that it will take me at least two months to get a beta of the product with feature parity vs. maybe a week to port the old codebase to the new API.<p>But on the other hand the C++ code is littered with stuff that 'just works' but can explode in your face and which eventually needs some safety net written around it. Which will likely take at least two months to do properly.<p>The truth is: after one and a half years of Rust C++ feels painfully ugly.<p>For context: I started with C++ with Borland's TurboC++ (moving from C) when I was 15. I used C++ for almost 30 years by now. It's about time.<p>[1] Yes, I did read <a href="http://adventures.michaelfbryan.com/posts/how-not-to-riir/" rel="nofollow">http://adventures.michaelfbryan.com/posts/how-not-to-riir/</a>
Most of what the author complains about w.r.t callbacks is fixed with std::function and lambdas (member function pointer syntax is necessarily weird, because methods aren't just normal functions). I definitely don't miss the days of std::bind. Nowadays you just do something like<p><pre><code> using Callback = std::function<int(int)>; // or whatever
Callback cbk = [&](int i) { return instance.method(i); };
</code></pre>
I've also seen some real evil hacks that rely on casting 0 as a pointer to a class and relying on the ABI's spec for vtable layout to calculate the pointer of the function as an offset from the `this` pointer. Because that's easier to remember than the syntax for pointer-to-member functions.
You can make C++ pretty: it's called D. <a href="https://dlang.org/comparison.html" rel="nofollow">https://dlang.org/comparison.html</a><p>Here's the D<->C++ intercompatibility project: <a href="https://wiki.dlang.org/Calypso#Current_status" rel="nofollow">https://wiki.dlang.org/Calypso#Current_status</a>
> The problem is that the default C++ string class is so utterly godawfully stupid. No garbage collection? Check. No refcounting? Check.<p>the irony is that in 2010, many std::string implementations were in fact reference counted (including libstdc++). This was generally considered a major mistake (because it doesn't work well with threads and when it does is a major performance pitfall) and prohibited in C++11.
Apenwarr‘s comment to this thread: „ I have since stopped trying to program in C++ at all. C is still ok, sometimes.“
[...]
„I want to like Rust; maybe someday.“<p><a href="https://twitter.com/apenwarr/status/1232848468156256256?s=21" rel="nofollow">https://twitter.com/apenwarr/status/1232848468156256256?s=21</a>
The followup article (<a href="https://apenwarr.ca/log/20100721" rel="nofollow">https://apenwarr.ca/log/20100721</a>) talks about a potential C/C++ replacement, and seems like a lot of points match up with Rust
<p><pre><code> [The [] operator] is an absolute
failure of engineering!
Do you want to know what real
engineering is? It's this:
map_set(m, 5, "foo");
char *x = map_get(m, 5);
</code></pre>
So like map::insert and map::at? Did these not exist in 2010?
Didn't got much better since then with regard to that aspect. IMHO C++ tried to adapt many features which had shown succesfull since then, but instead of properly putting them into the language they often got implemented in a way which I would describe as "somehow hacked in to try to avoid to actually introduce new features" but others might describe as implemented in a very C++ish way in symmetry to other features. Anyway the result is often sup-par. Not downright shit but worse then it should be and more important making the features work less good (from a complexity+usability POV) then in the languages they where copied from.
"C++ isn't a language, they say, it's a language construction kit! Build the language of your dreams in C++! And it'll be portable and scalable and fast and standardized!"<p>This is the power and achilles heel of Lisp as well.
<p><pre><code> > But in python, it works perfectly (even for
> user-defined types). How? Simple. Python's parser
> has a little hack in it - which I'm sure must hurt
> the python people a lot, so much do they hate
> hacks - that makes m[5]= parse differently than
> just plain m[5].
>
> The python parser converts o[x]=y directly into
> o.setitem(x,y).
</code></pre>
The name for this is "generalized variables", at least in Lisp land. The idea is to allow complex assignment left-hand side (LHS) expressions and turn assignments into calls to setter functions, including whatever complex data structure traversals might be needed.<p>Lisp has generalized variables via "setf macros", which turn assignments into the right set of calls to setter functions. Setf macros do this at compile time and generically for any getter/setter functions that have been registered with a bit of ceremony.<p>(Lisp also has destructuring-bind, which lets you write a data structure with variable symbols in it such that the corresponding variables will be bound to the data find in the corresponding places of a real data structure value. The two features, destructuring and generalized variables, are similarly magical.)<p>jq can do crazy generalized variable assignments like '.a[].b[0] = 1', but this is a run-time thing. (The LHS is evaluated in a context that allows only "path expressions", and in a reduction, while the RHS expression is run in the body of the reduction to update the input value at each path matched by the LHS.)<p>Icon implements generalized variables by letting procedures return "places" -- references to assignable locations --, so you can assign to the return value of procedures. This may seem quite surprising when you see it, but it works beautifully.
<i>"About the same time we were starting to work on Go, I read, or tried to read, the C++0x proposed standard and that was convincing to me."</i> -- Ken Thompson<p>Source -- <a href="https://www.youtube.com/watch?v=sln-gJaURzk" rel="nofollow">https://www.youtube.com/watch?v=sln-gJaURzk</a>
I love programming in C++ and I love this rant.<p>If you ever design a language you should hope that it gets popular enough that people bitch about it this hard. That’s a real triumph.
I 100% agree with the title, but some of the complaints in this article have been addressed since the article was published by C++11, C++14, or C++17. Others are just weird.<p>> If you've heard anything about C++, you've probably heard that there's no standard string class and everybody rolls their own.<p>Is this still true? std::string seems perfectly reasonable now, especially now that they've given up on supporting ropes and integrated the small string optimization. Yes it doesn't specify an encoding.<p>> No garbage collection? Check. No refcounting? Check. Need to allocate/free heap space just to pass a string constant to a function?<p>Nothing else in the standard library is garbage collected or refcounted by default. Why would std::string be the lone exception? You can opt into refcounting for any type using std::shared_ptr.<p>The objection about allocating/freeing heap space is about APIs that take const std::string& being passed C-string literals. Legitimate complaint, but it's addressed by std::string_view now.<p>> ...rant about lack of []= operator...<p>[] mutating the map does surprise people, so that's definitely a legitimate complaint. And it is annoying to have to use find() in a const context...<p>but simple operations like counting are simpler and more efficient in C++ than in Python because the +=, -=, etc operators work:<p><pre><code> for value in list:
counts[value] = counts.get(value, 0) + 1
</code></pre>
vs<p><pre><code> for (auto& value : list)
counts[value]++;
</code></pre>
> So actually C++ maps are as fast as python maps, assuming your compiler writers are amazingly great, and a) implement the (optional) return-value optimization; b) inline the right stuff; and c) don't screw up their overcomplicated optimizer so that it makes your code randomly not work in other places.<p>This is just comical. Python is not playing in the same performance league as C++, regardless of whether inlining or RVO happens. RVO of course is a general optimization for returning objects by value from functions, not a special case to optimize setting map items. It's still relevant, but less important since C++11's move semantics.
You mentioned that there's no standard string class for c++, and that python is your goto, would recommend looking at Dart Lang, extension methods have recently been added, it also compiles to native exec binaries. <a href="https://dart.dev/" rel="nofollow">https://dart.dev/</a>
That C code wouldn't work if the strings in the map are mutable (which they are in C++). It wouldn't work if the strings were allocated dynamically either. Once you write all the code required to get it working that way, the C starts comparing less favorably to C++.
The biggest issue with C++ for me is the confusing memory model. You have smart_pointers, you have move semantics, and then you have libraries like OpenCV doing their own refcounting (and also using std::shared_ptr). The C++11 features like lambdas are definitely welcome but at this point C++ epistemic footprint is just too large.
C++ is mostly an abstraction layer over C.<p>I would rather use C++ because i would have the option to use abstractions like std::map, std::string, std::vector, std::any etc. as they would save a lot of time and code complexity.<p>IMHO the worst thing about using C/C++ is getting other libraries to play with your project well even if you are using cmake or vcpkg, its not enough. You have to have solid knowledge of each operating system class to get everything working nicely over the long-term.
I certainly agree that Modern C++ is vastly bett... actually this is just someone posting an old polemic and trying to stir resentment/controversy. <i>IGNORE THIS CRITICSM OF C++</i>... there are much better and more relevant ones which are worth taking seriously. This is not worth taking seriously.<p>(I wonder how many of these posters are real or fake. Given the karma and post of this poster I'm inclined to... wait. Last comment was in 2017. Yet... hasn't too many posts since that, I think it's about 4. Probably a bit out of the loop, buy maybe not malicious.)