4 ms·
While my pet peeves might be different than the author's I agree that C++ makes you work very hard to keep things simple and produce something that is beautiful
by yason 9y ago
While my pet peeves might be different than the author's I agree that C++
makes you work very hard to keep things simple and produce something that is beautiful. Just "avoid the complexity you don't absolutely need" doesn't really work: some basic things are so fundamentally convoluted that I rather just write idiomatic C because it's simple and doesn't get in my way. I want the language to originate from simple axioms so that I can concentrate on the complexity of the problem I'm solving instead of wasting brain cycles on battling the complexity of the language. I would like to like C++ but its benefits barely zero out the extra hoops.
- thebear 9y agoAuthor of the blog post here. I think you just made me aware of the true and deeper reason for my discomfort with C++: it's the fact that the convolutions are in the basic things. I am perfectly willing to put up with convolutions, annoyances, bugs, weaknesses etc. in anything I use, be it a programming language, a piece of software, a gadget, whatever. Nothing is perfect, and who am I to criticize others for the imperfections in their work. What annoys me is when the annoyances are in the basic things, in the most commonly used features. Make the basic things reasonably good, and keep the crap off to the side.
- luk32 9y agoI'd be very careful with the claim that you are willing to put up with bugs. Bugs in language or compiler will make the language useless for any project which is expected to work. I'm gonna be bold any say that you nor anyone else would put up with it. There's enough bug in one's own code, there is rarely any space for unreliable infrastructure.
- athenot 9y agoThis reminds me of a goal Larry Wall for Perl when he was designing it: "make the easy things easy, and the hard things possible".
- mannykannot 9y agoI think that one reason the convolutions are in the basic things was the principle that C++ should be a superset of C, which is nominally a value-semantics language, but which, with the use of pointers, very commonly (and intentionally) leads to code with aspects of reference semantics. One example of this is that C++ adopted The C practice in which arrays decay to pointers. In addition, C++ not only inherited C's static-typing rules, but strengthened them, and complicated them with inheritance (multiple, and polymorphic or not, according to your needs), function overloads and operator overloading. Now add generic types through templates, and the cases to be handled explodes to the point where you need a Turing-complete parser. A good case can be made for each of C++'s features individually, which leads to justifications of the form "As we want both X and Y (and without sacrificing run-time efficiency), then there really isn't any alternative to [insert counter-intuitive issue here]..." That it works at all is a testament to the skill of the people involved. The complications that remain seem qualitatively different than the sort of gratuitous inconsistencies that you find in PHP, for example.
- AnimalMuppet 9y agoCould you give an example of "some basic things are so fundamentally convoluted"? Also note that almost all C code is legal C++, so when you "just write idiomatic C", you're still writing C++. (Perhaps not idiomatic C++...)
- yason 9y agoA simple case is hiding the implementation and exposing a public API. Let's use objects to make it something C++ ought to be good at and C ought to be bad at. In C, you write a header file adder.h: struct Adder; struct Adder *adder_create(void); void adder_setup(struct Adder *, int, int); int adder_operate(struct Adder *); void adder_delete(struct Adder *); You can easily imagine how one would trivially implement these functions in adder.c, allocating an object, mutating its state and deleting it. The caller doesn't know anything about struct Adder nor does it know how the adding of two ints is implemented. It only needs know that struct Adder can be pointed to. The header file defines a clear interface that can be compiled against. The implementation can be changed without having to recompile all callers. Tried-and-true and boring but it works: this is the way C has done it for decades. Now, C++. You create a class Adder, declare public constructor and destructor as well as setup() and operate(). Then you declare a couple of private ints to hold state and maybe some private helper methods, and then you realise that 1) you've just exposed parts of the private implementation in the public header and 2) you can potentially break compiled binaries even if you only change the private/protected parts of the class. Yes, that's a textbook example of how to define a class that completely sucks for any real-life encapsulation purposes. You see how things are getting complex quick? This is where people began to think of more novel applications of C++ to fix the language itself. So you define an abstract class IAdder in adder.h with pure virtual methods to act as a truly public interface, and derive an implementation class AdderImpl in adder.cpp. Great. Except you can't instantiate the private implementation. You'll need a public factory function outside the class or a static method such as IAdder::create() to construct an AdderImpl and return it as an IAdder. This isn't very clean and beautiful anymore and this was a simple example. There are more branches to be explored in the solution space but at this point we've basically had to create an ugly reimplementation of something that we thought would come free in a language that namely supports object oriented programming whose one fundamental selling point is easy encapsulation. And all that while the C counterpart is actually easy, understandable and simple, and requires no re-engineering to get it even work.