Hacker News new | past | comments | ask | show | jobs | submit login
"Within C++, there is a much smaller and cleaner language struggling to get out" (stroustrup.com)
54 points by _mtkq on Jan 31, 2020 | hide | past | favorite | 52 comments



Sometimes C++'s evolution reminds me of the quote from Antoine de Saint-Exupery: "Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away." [0]

When the topic of C++'s huge and growing complexity comes up, opinions mostly fall into two groups: (a) the language is way way too complex, and (b) ... yeah, but modern C++ is really clean and you can just ignore all the complexity that's been retained for backwards compatibility.

I don't find (b) persuasive because every line of C++ code is interpreted by the entire language standard. If (b) really is true, then I'd be interested in seeing a new language that has only the subset of the C++ standard considered "modern". If that language was actually useful, I'd eagerly use it in practice.

[0] https://www.brainyquote.com/quotes/antoine_de_saintexupery_1...


Stroustrup has written quite a bit fighting against complexity:

> There are two fundamental ways of approaching the unavoidable uncertainty in a design:

> • add “improvements” until everybody feels well served

> • cut until there is nothing left to cut and all there is left is principled and fundamental

> After both approaches, experience will show the need for changes (pre-release) and additions (all we can do post-release). I clearly favor the second approach and consider it proper engineering based on principles and feedback. I consider the former hacking and politics. In a standards process, compromises are necessary, but we must try to ensure than compromises are not between irreconcilables or just union-of-features bloat.

He continues:

> Stability is a feature as well as a serious design constraint. [....] I can summarize most people’s attitude:

> • “C++ is too complex. We need to make it smaller, simpler, and cleaner.

> • And please add these two features.

> • And whatever you do, don’t break my code!”

Source: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p196...


> I can summarize most people’s attitude

I’m skeptical that there is a significant body of critics that share these patently conflicting views. More likely there are different groups who each value one of these, or more likely still, lots of individuals like me who are fine with specific, entirely consistent concessions from each of these major categories. For example, I would like to see C++ support some sane build and package ecosystem and I’m ok if it breaks my projects. I would also be happy to do away with the C compatibility requirements.

It would probably be too much to ask to re-evaluate every design decision that was predicated on C compatibility, but I would be okay with reevaluating them gradually over decades, deprecating language features here and there. In general we need to get rid of the idea that we only need to write software once and then every future version of the toolchain will support it. Instead I would like to see a world where the language changes gradually and project maintainers simply have to make small, almost mechanical changes every 5 years or so.


> I’m skeptical that there is a significant body of critics that share these patently conflicting views.

If I take a serious look at my own C++ needs I do find myself having those contradicting views. Essentially what I find is that for areas of the language that do not pertain much to my day to day work I'm fine with "simplifying" (even if it means removing features, because I don't need those features) but for the things I work on (which I'll be the first to admit are likely quite rare in the general C++ population) it would be a deal breaker if the features that I use but most other people don't get removed.


Those aren’t contradictory views; you are consistent, but your views aren’t consistent with those of the “other people” you refer to, which is my point.


I think it depends on how you frame it. "If we could just add this one feature, we could get rid of these five crufty features that I think are obviated by it" is a fairly common sentiment in my experience.


The problem is that everyone's ideal subset of C++ is different because everyone has different requirements!

"A lot of software developers are seduced by the old ‘80/20’ rule. It seems to make a lot of sense: 80% of the people use 20% of the features. So you convince yourself that you only need to implement 20% of the features, and you can still sell 80% as many copies.

Unfortunately, it’s never the same 20%."

https://www.joelonsoftware.com/2006/12/09/simplicity/


C++ is probably a little different. There’s a lot of ways to do things due to accumulated cruft, for example. I’d wager at least a good 20% of C++/STL is to some degree redundant.


Worth keeping in mind: Joel's pulling stats from a very dark spot, located somewhere behind.

In reality, there are common features, and there are rare features - there's just rarely a product manager willing to give up users for clarity of vision.


> but modern C++ is really clean and you can just ignore all the complexity that's been retained for backwards compatibility.

I actually think the opposite. Modern C++ is painful, but a subset of it, mostly the stuff prior to the introduction of templates, is very useful and clean.

But I also think this is a strength of C++: you really can realistically decide what parts are appropriate to use in a project and what parts to ignore.


With due respect - prior to the introduction of templates is _super old_ C++.

"Modern C++" means C++11 and later versions. It uses templates extensively, leaning towards more compile-time computation rather than relying on run-time polymorphism.


idk, I think some of the things added after templates were added in 1990 are pretty useful, like `bool`, `static_cast`, `std::vector`, etc


I'd also add unique_ptr. Being able to have a heap-allocated object under RAII is a godsend.


Yes, I agree. My objection is really the template syntax itself. There have been many things added over the years that are good.


Could this essentially be achieved with a linter rather than a whole new language?


I am sort of agree.

In practice however I use comfortable subset of it and then it is simple. This is my (b). I know that everyone has their own idea about what said subset should be but I do not participate in large C++ teams and hence it is not a real problem for me.

So yes in general you're right, in practice some people are ok. What's the real percentage of those I have no idea.


"There are only two kinds of languages: the ones people complain about and the ones nobody uses" is his other famous quote. I agree with you that (b) isn't that persuasive. C++ is one of those languages where the organisation using it kind of has to enforce their own subset for things to stay sane.


Rust is close enough to that language.


Language keywords are like ingredients. You don't have to use it all when cooking. Something that most organizations and folks don't do is constraint what they are going to use. They figure, it's all out there for the taking, so use it all. It's always a pleasure when one comes across a group that have thought deeply about the nature of the work and selected a subset of the language they need to use. This is very important when dealing with a huge beast like C++. Just like if you go to AWS, figure out what you need, don't try to use all their services, decide on what you will not use too.


C--


C-- is a pretty weird language basically only useful as a backend for GHC.


I was utterly unaware that it was real. I was in fact trying to make a joke. Thanks for the enlightening.


«"Within C++, there is a much smaller and cleaner language struggling to get out". Yes, that quote can be found on page 207 of The Design and Evolution of C++. And no, that smaller and cleaner language is not Java or C#. The quote occurs in a section entitled "Beyond Files and Syntax". I was pointing out that the C++ semantics is much cleaner than its syntax. I was thinking of programming styles, libraries and programming environments that emphasized the cleaner and more effective practices over archaic uses focused on the low-level aspects of C.»


The small clean language wasn't really there. Not having sum types is why exceptions are like they are. Not having had first-class functions until recently is why control flow is like it is. Not having a proper type system is why templates are like they are. Those things between them are why concurrency is the way it is. You can't remove things from C++ to get a nice language - you need to start with a better foundation.


It's not just language: it's support, tools, compiler etc.

I just spent a day trying to get C++ working properly for a specific project in MSVSCode, surprisingly, it won't work, there are arcane and cryptic bits of help on StackExchange, and the sheer amount of inclusion variables, paths, special cases, compiler settings etc.. is beyond bewildering.

It takes far too long for someone to develop the competency just to manage anything more than a trival build and this is a failure of the language because there's simply no reason for it - it's 'arbitrary complexity'. We're wasting serious chunks of our lives solving problems that shouldn't exist in the first place.


As https://blog.plover.com/Unix/tools.html says:

The bizarre mishmash of weirdness exists because so many different people invented so many tools over such a long period. And they wouldn't have done any of that inventing if the compositionality hadn't been there. I think we don't actually get to make a choice between an incoherent mess of composable paraphernalia and a coherent, well-designed but noncompositional system. Rather, we get a choice between a incoherent but useful mess and an incomplete, limited noncompositional system.

I agree that C++ development can be a mess. But it is often a mess for good reasons, not bad.


Yea, I agree. That's a good quote.

I also would really like a 'strong agent' to just come along and do a 'new C++' without the cruft, kind of along the lines of the 'go' philosophy without necessarily inventing a new language.

Maybe Rust is de-facto that. Or maybe D is it and we're not playing close enough attention.

I guess your point is further validated by the hot mess of the web as well: javascript is a monster, somewhat tamed by TypeScript ... and I don't think Dart or anything else is poised to replace it.


We are actually seeing it gradually, but not as the smaller-cleaner language. Rather, as cleaner idioms channeling the spirit of that language - within an ever-widening C++.


> spirit

I think it would be a good name for the new language (if it ever shows; it will probably be a lisp).


That's like saying Rust will turn into Lisp.

There is way too much around memory management to be Lisp.


If by "it" you mean the much smaller and cleaner language within C++, no, it will absolutely not be a lisp.


you are so right! i too love that name for a programming language. i vote for a modern, typed curly-less language, with written end of blocks if that's not too much to ask :)


Agreed.

RAII, smart pointers, optional...C++ is become cleaner and cleaner.

Unfortunately, that's not simpler, as the old stuff still works too.


There are competing ideas of how to get to a world where C++ can have both (1) backwards compatibility and (2) the removal of old language features.

Some people disagree with that concept entirely (including Bjarne, IIRC) because of the fear it will fracture the language. But luckily the conversations and proposals are actually happening.


Yes, I can see it too the coroutines in C++20 is a nice step in that direction.


My favourite Stroustrup quote on the design of C++ is probably from "How can you be so certain?":

> One of my fundamental aims for C++ is (from the very start in 1979) to provide equally good support for user-defined and built-in types. For example, I’d like to be able to build an integer type that is as good as the built-in int in every way


It would be kind of neat if there was a definition of different levels of the language and you could specify which level you allow in the file. This would be stronger than running a code style analysis tool. Not sure how viable this is but it would be nice to somehow phase out things like auto_ptr and others in projects.


The problem is no one can agree what that language is.


It's not really true that "the semantics of C++ aren't that complicated".

Once you take into account undefined behavior --- which you need to, so you can avoid it --- it's so complicated that researchers haven't yet figured out what those semantics are.


...and that "smaller and cleaner" language is C. ;-)

I'm only half-joking, of course; but while I see the beginnings of C++ were humble and practical, as a way of simplifying common idioms in C, it seems that lately the emphasis is more on turning the abstraction level to 11 with things like deeply-nested deeply-parameterised templates and writing otherwise "opaque" code that is short at a glance but entails considerable and often needless hidden complexity. I think Stroustrup himself is somewhat aware of that, given that he even references the infamous "fake interview" on that page --- and while that was a fake, the sentiments expressed in it certainly have a basis in reality.


That's pretty much the opposite of the point he was making. His context is:

> I was thinking of programming styles, libraries and programming environments that emphasized the cleaner and more effective practices over archaic uses focused on the low-level aspects of C.


Why do we need to try to streamline C++ here? What's behind the urge to "cut out the fat"? Would doing this make C++ an even better performing language? What's the upside of gutting the language?

I don't understand the impulse here. Yes, the semantics of C++ are more elegant than the syntax. But that doesn't mean that the syntax is actually cumbersome.


Having so much syntax makes the language more difficult to learn, and you have to know the edge cases of each.

It's universally recognized that, since C++11, you should use the `nullptr` keyword to create a null pointer. `nullptr` solves problems like not being implicitly convertible to integers, so you don't get the wrong overloads or template specializations.

However, it's still perfectly valid to initialize a pointer to the NULL macro, etc. There's no benefit, but it's still all throughout codebases, so people will keep using it. Wouldn't it be nice if there was just one way to initialize a null pointer in new code?


> What is "legacy code"?

> "Legacy code" is a term often used derogatorily to characterize code that is written in a language or style that (1) the speaker/writer consider outdated and/or (2) is competing with something sold/promoted by the speaker/writer. "Legacy code" often differs from its suggested alternative by actually working and scaling.

Oh? To me legacy code is code that's been put into production. The moment it's in production, you have to maintain it, you have to worry about backwards compatibility and interoperability. The moment it's in production the field is no longer green.

Perhaps production code is only legacy code the moment you want or have to change it, but since that almost always ends up happening, so the moment it's in production, it's legacy.


That smaller language is basically the C++ described in the Annotated C++ Reference Manual (a.k.a. Brown Book) by B. Stroustrup and M. Ellis, published in 1990.

I landed into my first C++ job not knowing C++. Friday was my last day on the previous job. I helped myself to a stack of paper and printed out the entire ISO C++ draft standard. I also got that ARM. I read the ARM over the weekend, then went to the new C++ job Monday. I was C++ "answer guy" a month later.

This one: http://www.stroustrup.com/arm.html


"... and we will find that language, and we will kill it."


If they take the C out of C++

Call it ++

Basically get rid of everything that the legacy of C brings.

If you want those things you probably should be coding C.

Get rid of the headers .h etc. Build that from the source .pp files

Make a standard package library that works properly on all platforms.

Standardize the internal symbols.

Make templates / everything easier to use, make standard internal map and vector types.

Change auto to var.

Kinda like the way go did it.

Sorry, too late!


> Basically get rid of everything that the legacy of C brings.

This is actually happening, but not literally. That is, most of the things you used to write in a C-like fashion - you no longer write today:

* References or plain values instead of pointers.

* std::arrays or other containers instead of plain arrays.

* std::variant's instead of unions

* std::expected instead of returning error codes (although error handling is a really complex issue)

and so on.

> Get rid of the headers .h etc.

This will start to happen in C++20, with modules.

> Make a standard package library that works properly on all platforms.

The standard library works well on many platforms. If you mean package management systems - that's never part of the language; but you can check out https://conan.io/

> Standardize the internal symbols.

Sort-of happening with modules, if I understand what you mean.

> Make templates / everything easier to use,

C++ features are actually easier to use as the standardization progresses.

> make standard internal map and vector types.

Whaaat?! Ha ha ha, certainly not. You really don't want that.

> Change auto to var.

That is rather inconsequential...

> Kinda like the way go did it.

What you suggested is in no way specific to Go.


Templates are easy to use? The messages that come about from getting them wrong aren't always the best though.

I don't understand why people want to get rid of headers at all? Can anyone explain why? In C# I have no headers and I find it far more difficult to read a class or get an overview.

"make standard internal map and vector types" What do you mean by this? I want to be able to use the right container for the job. I don't want a dumb array of any type like PHP arrays. That's appallingly bad because you can above garbage into them and the user of the array has no guarantees about what is in it. Might as well use void* everywhere and chuck the type system in the bin if you really want that? Or have I misunderstood?

Also changing auto to var - why??


I use what I call "C+" which is C plus classes, basic templates, and light polymorphism when it is absolutely perfectly suited. I'd like to explore a lot of the later features but I haven't had the drive to do it. I write a ton of embedded C for money and learning C++ has lifted my C skills tremendously. It forces you into certain paradigms that you can easily do in C if you have the discipline.


As a primarily C++ developer, I absoloutly hate maintaining code that is written like this. C has it's place in the world, but despite the fact that the language has a large amount of overlap in syntax, they are very different languages. Trying to write one in the style in the other will, at least from me, earn you some very bad thoughts.


I agree. The more code looks like C or early '90s C++ (not to say Java), the worse it is. The newest language features exist because the language is better with them, and code is better when it used them.

That is not to say that every function, or every program, has to use every obscure feature. Many features are there only to support very specialized use cases (which absolutely exist, and are important!). But things like new-style loops, generic lambdas, structured bindings, and little helper templates make writing and reading code enormously more pleasant.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: