HN Theater @HNTheaterMonth

The best talks and videos of Hacker News.

Hacker News Comments on
CppCon 2016: Dan Saks “extern c: Talking to C Programmers about C++”

CppCon · Youtube · 86 HN points · 11 HN comments
HN Theater has aggregated all Hacker News stories and comments that mention CppCon's video "CppCon 2016: Dan Saks “extern c: Talking to C Programmers about C++”".
Youtube Summary
http://CppCon.org

Presentation Slides, PDFs, Source Code and other presenter materials are available at: https://github.com/cppcon/cppcon2016

Most of us have heard this story. We’ve even told it ourselves…

C++ is nearly all of C, plus a whole lot more. Migrating code from C to C++ is pretty easy. Moreover, the migration itself can yield immediate benefits by exposing questionable type conversions that can be sources of latent bugs. After migration, the code performs as well in C++ as in the original C. And now that it’s C++, you have ready access to a wealth of advanced features you can (but don’t have to) use to implement enhancements.

Who wouldn’t want that? Legions of C programmers, apparently.

Despite the success of C++ in numerous application domains, C remains considerably more popular, especially in embedded, automotive, and aerospace applications. In many cases, projects resist C++ because their managers think the risks outweigh the benefits. In other cases, the resistance comes from programmers who persist in believing bad things about C++, even when those things aren’t true.

What can the C++ community do to overcome this resistance? Drawing on lessons from cognitive science, linguistics and psychology, and (of course) computer science, this talk offers suggestions about how to make the case for C++ more persuasive to C programmers.

Dan Saks is the president of Saks & Associates, which offers training and consulting in C and C++ and their use in developing embedded systems. Dan used to write the “Programming Pointers” column for embedded.com online. He has also written columns for numerous print publications including The C/C++ Users Journal, The C++ Report, Software Development, and Embedded Systems Design. With Thomas Plum, he wrote C++ Programming Guidelines, which won a 1992 Computer Language Magazine Productivity Award. Dan has taught C and C++ to thousands of programmers around the world. He has presented at conferences such as Software Development, Embedded Systems, and C++ World. He has served on the advisory boards of the Embedded Systems and Software Development conferences. Dan served as secretary of the ANSI and ISO C++ Standards committees and as a member of the ANSI C Standards committee. More recently, he contributed to the CERT Secure C Coding Standard and the CERT Secure C++ Coding Standard.

Videos Filmed & Edited by Bash Films: http://www.BashFilms.com

*-----*
The CppCon YouTube Channel Is Sponsored By:
JetBrains : http://jb.gg/cpptools
SonarSource: https://www.sonarsource.com/
*-----*
HN Theater Rankings

Hacker News Stories and Comments

All the comments and stories posted to Hacker News that reference this video.
I wonder if the reason for there being no C language conference is: It's generally accepted that C is "dead" or should become dead. In fact at C++ conferences you will see many anti-C talks:

* https://youtu.be/YnWhqhNdYyk

And also talks promoting proselytizing to C programmers and bringing them to C++:

* https://youtu.be/D7Sd8A6_fYU

And of course, now, Rust is supposed to supplant C.

It is a culture problem, something that only will change with mentality reboot.

"CppCon 2016: Dan Saks “extern c: Talking to C Programmers about C++”"

https://www.youtube.com/watch?v=D7Sd8A6_fYU

"Writing better embedded Software - Dan Saks - Keynote Meeting Embedded 2018"

https://www.youtube.com/watch?v=3VtGCPIoBfs

"Embedded & C++ - Meeting 2017 Keynote"

https://www.youtube.com/watch?v=mNPfsUZb3vs

In a way, the same kind of subculture in C++ that jumps in cries of horror if you happen to use std::vector/array/string with bounds checking enabled.

lmilcin
I think the basic issue is that C++ want to spend a lot of time focusing on C++ The Language, while C developers mostly want to focus on developing the logic of whatever they are doing.

When I worked on C++ projects half of the discussion was on just the use of language or various consequences of it.

On C projects that never happens. There is nothing to talk about so everybody focuses on making the project better.

Things I don't miss after I switched from C++ to C:

-- discussing compiler feature set,

-- discussing how exactly to format complex C++ constructs,

-- regular calls for help from less experienced devs to more experienced C++ "gurus" for their wisdom to just interpret what the code does or tell them how to write the thing they want to write,

-- trainings for less experienced developers so that they can even understand the syntax of the code,

-- hunting bugs due to lack of understanding of complex internal mechanisms,

-- having hard time working with a debugger on complex code,

-- not being able to tell wtf is the exact type of the thing that I am looking at or what exact code is going to get execute when I use an operator or call a function. The IDE not being able to locate it for me is an added "bonus".

pjmlp
What I miss most when working in C instead of C++ is that although lint was created in 1979, most projects still avoid any kind of static analysis.

Then there are the discussions on:

- what warnings to turn on as errors

- what ISO C says and what compiler XYZ does, with many not even aware to the differences

- not clear understanding of the 200+ UB cases documented on the standard

- in-house libraries for safer handling of strings and arrays

- experienced developers creating CVEs because they think they are free of such errors (pun intended)

citrin_ru
Almost all above applies to C++ too.
pjmlp
It does indeed, with the big difference that C++ community cares to reduce the amount of UB on the standard, and pushes for language features that improve safety.

Now if people choose to ignore the tools available to them, just like they enjoy ignoring lint since 1979, well there is little the doctor can do to save patients that refuse help.

twic
> I think the basic issue is that C++ want to spend a lot of time focusing on C++ The Language, while C developers mostly want to focus on developing the logic of whatever they are doing.

This is just libel, really. There are meta-nerds in C and C++, but there is also a great majority of programmers just interested in delivering good software.

Because it is a culture pretty much anti-C++, to the point that it is a common theme in C++ conferences how to succeed selling C++ to those communities, for example,

"CppCon 2016: Dan Saks “extern c: Talking to C Programmers about C++”

https://www.youtube.com/watch?v=D7Sd8A6_fYU

lpapez
Highly recommend watching this talk. The lessons conveyed by the author will serve you well not only in communication with C programmers, but communication with anyone really :) As the first comment on the video says: "I came here for a C++ talk, walked away with a life lesson"
enriquto
is there a text transcription of this talk for video-impaired readers? (I'm deeply triggered by the obvious falsehoods in the description paragraph, and I have morbid curiosity about the rest of the thing.)
The mentioned cppcon presentation by Dan Saks is awesome. Highly recommend watching even if you are not interested in C or C++ : https://youtu.be/D7Sd8A6_fYU
Sure it is for political reasons when even C99 is seen as too modern, and many are unwilling to let go of C89 and Assembly even if the OEM toolchain supports modern C.

And for another point of view of someone more relevant than my insignificant self,

CppCon 2016: Dan Saks “extern c: Talking to C Programmers about C++”

https://www.youtube.com/watch?v=D7Sd8A6_fYU

"Embedded Development with Dan Saks"

http://cppcast.com/2016/10/dan-saks/

Thankfully there are industry certification standards like AUTOSAR, which now require C++, so those devs can choose to keep grasping to C and switch industry or learn more modern languages.

You can ask Dan Saks about it.

CppCon 2016: Dan Saks “extern c: Talking to C Programmers about C++”

https://www.youtube.com/watch?v=D7Sd8A6_fYU

Embedded Development with Dan Saks

https://cppcon.org/leveraging-modern-cpp-for-embedded-system...

When I started coding in C++ (Turbo C++), 640 KB were just fine, I could even make use of a full TUI framework (Turbo Vision).

Hence my point of view about PIC class processors with single digit KB, being eventually the only target not possible to use with C++, unless one wants to suffer a bit with linker scripts.

C is king because the industry is currently dominated by people who have been doing this since before C++ was a thing.

Additionally, most of these people are primarily electrical engineers, and don't have as strong of a background in computer science. They've been using C for decades and it does everything they want, why would they take the time to learn the boundless complexity introduced by a language that offers them (what they perceive to be) very little?

Talking to long-time C programmers about C++ is actually surprisingly difficult: https://youtu.be/D7Sd8A6_fYU

pknopf
Let me ask it this way:

I'm a higher level programmer. Later in my career I happen to get down to microcontrollers, what would stop me from using C++?

shakna
A lot of people do. But they may as well not. They tend to write C-style C++.

Simply put, because you can't use the STL, or a lot of other C++ features, or only with a lot of consideration.

A whole swathe of the embedded world still cares about program size in bytes. There are some that don't, but they tend to be using Linux, and are at a higher abstraction level than many others in the industry. (Industry is kinda divided in half. Those who use tiny Linux machines, and those working with microcontrollers. It's a generalization, but generally fits.)

The stuff I work on day-to-day, usually has between 1-4kb for dynamic memory, and 8-16kb for the compiled program. That line is also usually a bit blurry, and you can move things between both at runtime, but at various costs.

With C++, you get tempted to use stuff like vector, which can blow your memory stack.

I generally work with C++, but it looks like C. I get a few things like implicit pointers, for free, but generally still have to end up making most things explicit.

But, unlike twenty years ago, I no longer have to dive into assembly unless the project is pushing it's limits. The compiler tends to be "good enough".

dmitrygr
It really depends how you use it. If you are approaching from the standpoint of "I am writing code on a microcontroller", which means no exceptions, no static initializers, probably no templates, definitely no rtti, then it will be all okay. If you approach it from the standpoint of "I'm just programming, how hard could it be? Let's just use std::", you're going to have a very bad time and very quickly.

C++, when used in that way, tends to do a lot of things behind the scenes. This is perfectly okay in a place where you have an operating system and a linker that have your back. On an embedded system none of this is guaranteed.

bleke
note, static initializers works in embedded you need to execute functions between __init_array_start and __init_array_end before using any static object in gcc somewhere in program
dmitrygr
I'm well aware of that. But giant array of static Constructors makes it hard to reason about when any piece of Hardware is accessed since a lot of stuff happens before Main (). Especially for people who don't play with the insides of linkers for fun on weekends.
bleke
Sorry that sounded like i'm scorching you i didn't mean it. Yes agree with when using HW initializing code in constructors I ended with two types of 'constructors/inits': 1 - for object initialization 2 - just for hardware and calling manually :/.
monocasa
Static initializers and templates are great in a deeply embedded context, IMO.
makapuf
Constexpr init can also be great in that case To initialize rom with complex objects.
dmitrygr
For you yes, since you know how they are implemented at linker level. But get a few junior devs on your team, and you'll be wondering why hundreds of thousands of cycles run before main is called, or why some driver code is being entered before it is initialized, since someone decided to make a static singleton object for some driver and called some driver method in the constructor which will run before main(), not realizing how this stuff really works underneath.

So, C++ can be a wonderful tool in proper hands, but it is much easier to misuse than C in an embedded context.

monocasa
I lead a team of six, including some junior devs.

How initialization occurred (static or otherwise) was just something we made an explicit check off item in code review.

dmitrygr
Awesome. Glad it worked out for you. I hope it stays so after you leave the team or no longer have time for each code review.
adrianN
If you let junior programmers fuck up your codebase that much, that's not the junior's fault. You should do code reviews.
jwhite
Nothing. I've worked on Cortex-M4 projects in C++. It's nice in many ways. The people working on the project had a much more diverse background than the typical EE who learned C as an undergrad mentioned in another thread.
Animats
Not much. The Arduino programming environment is really gcc in C++ mode, but a different library.
q3k
The standard library (with all its' duplicate code resulting from hardcore templating) will blow up your flash space usage significantly, to the point where you will run out of it sooner than you expect. You will spend time finding alternative standard libraries that are size-optimized and you might end up rewriting a lot of what you take for granted in your C++ daily usage. For example, the Arduino environment is C++-based, but it's not anything like on the desktop due to it not shipping an std:: .

Your typical heap-happy usage will not go down well on a microcontroller, either. Having very constrained RAM makes heap fragmentation much more of an issue.

atilaneves
Then don't use the standard library. Don't even link it in.

> Your typical heap-happy usage

Huh? 1990s C++ was typically heap-happy, which is part of the reason Java looks the way it does. Idiomatic modern C++ uses the stack as much as possible. And one can use custom allocators.

pjc50
Not a good fit for systems with small hardware stacks - PIC16 is still in use http://www.microcontrollerboard.com/pic_memory_organization....
bb88
> C is king because the industry is currently dominated by people who have been doing this since before C++ was a thing.

No. If C++ were a great language those C coders would have moved over in an instant. One of the advantages of looking at C code is that you can actually figure out in your head what the assembly will look like.

ShroudedNight
> One of the advantages of looking at C code is that you can actually figure out in your head what the assembly will look like.

One can do this with most C++ too. Though admittedly, non-tree virtual inheritance hierarchies, as well as member function pointers [et al] make this harder to achieve universally. I will also admit that it's easier to do with C.

If the optimizer gets its hands on either though, you may be in for a surprise no matter your choice.

vardump
C++ extra object copies can sometimes be pretty difficult to see without checking disassembler listing.
pjmlp
Only when compiling without any kind of optimizations, nor using vector instructions.

In any case, C++ is copy-paste compatible with 99% of C89. So same benefits apply when using that subset.

It is plain language religion as observed at a few C++ conference talks.

bb88
I think you're not giving engineers enough credit here.

The world moved from C++ to Java on the enterprise side back in the late 1990's. Why? Java was arguably faster and easier to develop in, even though many thought (including me) that C++ was technically a better language.

pjmlp
So, I will let one of the renowned experts speak instead.

CppCon 2016: Dan Saks “extern c: Talking to C Programmers about C++”

https://www.youtube.com/watch?v=D7Sd8A6_fYU

Embedded Development with Dan Saks

http://cppcast.com/2016/10/dan-saks/

Regarding Java vs C++, yes the enterprise world has adopted Java, however as someone doing consulting across Java, .NET and C++, I am really seeing it coming back since ANSI C++ has picked up steam again.

I see it in projects related to IoT, AI, VR, big data,....

They are all polyglot projects with C++ plus something else, not C plus something else.

freeone3000
It is very hard to get a Java or Python programmer (what those AI guys want to use) to move to C, even if they HAVE to use something native. So C++ is where they end up.
pjmlp
This whole thread started about embedded development.

As noted, unless we are speaking about PICs with 8KB and similar, the majority of them can easily be targeted by C++, which is what Arduino and ARM mbed do.

Already in MS-DOS, on 640KB computers, using C made little sense.

When we needed performance, Assembly was the only option, because the code any compiler was generating in those days was average quality on their better days.

When performance wasn't that critical, then the improved type system, RAII, reference types, type safe encapsulations were already better than using plain C.

We even had frameworks like Turbo Vision available.

So if something like a PCW 512 didn't had issues with C++, so a modern micro-controller can also be targeted by it, except for political reasons.

Developers that are against anything other than C, even if their compiler nowadays happens to be written in C++ (e.g. gcc, clang, icc, vc).

pknopf
Ah, I forgot about the assembly.

Is assembly important in microcontrollers?

tluyben2
Because of cost we use very constrained microcontrollers; every byte literally counts. In the end it really matters cost wise (in mass production embedded every cent counts as well; using a high spec mcu just costs more) but we had to rewrite from C to assembly to get a few more kb for features in the flash. C++ or Rust are generally not good for the cost of materials.
pjc50
Writing assembly tends to be restricted to the bits where you need it - special function prologues for interrupt handlers, requiring a particular unusual instruction for something, time-sensitive or cycle-accurate "beam racing" code.

Reading assembly is more useful, especially if your platform's debugger isn't very good.

torn_pages
I would say it does. I learned microcontroller programming in assembly before I learned about C.
viraptor
Sometimes. Usually you just write "normal" C, until you realise your single `sprintf` use took 20% of your ROM size. Or until you need some interrupt handler to take no more than N cycles. You probably don't switch to assembly at that point, but you definitely start checking what the compiler output is and where are the bytes/cycles wasted.

Actually writing assembly is more of a last resort time.

atilaneves
They'd move over if technical considerations were the only reason why people choose programming languages. In my experience it tends to be psychological ones.

> you can actually figure out in your head what the assembly will look like

I keep hearing this, and I don't buy it. Did you know that `gcc -O3` will turn `int add(int x, int y) { return a + b; }` into an `lea` instruction? I doubt many people do.

And it's not like the compiler will magically switch to emitting different instructions if you compile the code above as C++...

vardump
> I keep hearing this, and I don't buy it. Did you know that `gcc -O3` will turn `int add(int x, int y) { return a + b; }` into an `lea` instruction? I doubt many people do.

Uh. That's a pretty obvious one.

Sometimes using address generation ports is preferable to ALU ports.

Also 'lea' can load the result in a different register from both operands, 'add' will always need to modify a register.

People have been using 'lea' for calculations since dawn of time, for example:

  shl ebx, 6
  lea edi, [ebx*4 + ebx + 0xa0000]
  add edi, eax
== y * 320 + x + framebuffer address.

This was a common way in DOS days for calculating pixel address in mode 0x13.

koffiezet
Psychological ones? No, simply the lack of available reliable compilers for some platforms was my problem. I developed POS applications, where C++ would have worked fine, if we had a decent C++ compiler on every platform we wanted to support. Some platforms used GCC, but most used proprietary compilers - where C++ support was completely absent or very scetchy. When you can't use exceptions, the memory allocator is absolute garbage and leaks stuff on it's own and encounter various random compiler bugs, you quickly decide to stick with plain old C. C++ in my experience was an absolute mess when it came to embedded work (note that the last embedded work I did dates back from 2006, so not sure what the current situation is)

Also, C++ uses a lot more memory, which can also be a no-go when you get as little as 32kb for code+data, luckily with in-place execution.

pjmlp
Modern C++ does just fine on a Commodore C64.

CppCon 2016: Jason Turner “Rich Code for Tiny Computers: A Simple Commodore 64 Game in C++17”

https://www.youtube.com/watch?v=zBkNBP00wJE

bb88
Sad that it took C++ almost 40 years to get there.
pjmlp
I was doing C++ development on MS-DOS already in the 90's.

Never cared for C beyond using it in Turbo C 2.0 for MS-DOS, and later when required to use it for university projects and client projects that explicitly required ANSI C89.

So it wasn't 64 KB, but it was perfectly usable on 640 KB systems.

The main problem has always been fighting misconceptions.

AnimalMuppet
> Also, C++ uses a lot more memory...

Depends on how you use it. "If you don't use it, you don't pay for it" is the C++ philosophy. If you use it as "C with objects", it should use no more memory than C with structs. If you use it as "C with polymorphism", it should use no more memory than C with function pointers.

I mean the embedded systems where Assembly and C89 still rule, and there is very hard to change, because the problem of adopting anything else is cultural.

Basically, while there are projects being done in C++, and many companies are finally migrating from C to C++, the large majority is sticking with C.

If you prefer to listen to someone actually relevant in the C++ embedded community, here is what Dan Saks has to say about it.

https://youtu.be/D7Sd8A6_fYU

http://cppcast.com/2016/10/dan-saks/

according to dan saks, who apparently to some people is famous c++ is faster than c (well in the test setup he describes below)

https://accu.org/content/conf2015/DanSaks-Embedded%20Program...

    Language   Design Implementation  Relative Performance
    either any inline 1 (fastest)
    C++ polystate non-inline 1.56 x fastest
    C++ bundled non-inline 1.65 x fastest
    C polystate non-inline 1.70 x fastest
    C bundled non-inline 1.79 x fastest
    C++ unbundled   non-inline 1.82 x fastest
    C unbundled   non-inline 1.95 x fastest
He furthermore argued that the biggest mistakes C++ developers did to kill the adoption of C++ for C programmers was to diverge from the previous line of "C++ is a better C" to "if you're using C++ as a better C you're doing it wrong"

https://www.youtube.com/watch?v=D7Sd8A6_fYUI

(I have no skin in the game, I was just curious to see if it's worth looking at rust for embedded when I came across that talk)

humanrebar
> "if you're using C++ as a better C you're doing it wrong"

As far as correctness and safety goes, this is still true. It's difficult to scale systems-level programming to large teams. C++ gives the opportunity for more explicit semantics and more aggressive compile-time checks. C can scale well and can be used safely, but you need to do a lot more through convention (always call xyz_Create and xyz_Destroy in pairs!) and through runtime checks (calls to assert, unit testing).

D, Rust, OCaml, and a few other projects are interesting in this space since they provide some of the same benefits as C++ with respect to correctness and safety. Some are plausibly better in theory, though I'm not aware of huge, say, Rust projects that approach the size of huge C++ ones.

khitchdee
Agreed. It's the size and type of the project that determines the choice of language more than the newness of the language. C++ was designed to meet the requirements of certain types of projects that were coming into vogue at the time it was designed. It was not a replacement for C.

Some of the structural advantages of C++ over C can be achieved in C by using generative programming for example and building in automatic mechanisms to ensure there are no memory leaks for example. In other words, the C++ approach to structuring programs is not the only way to achieve the benefits that that structuring implies. It's just really easy to do it that way.

pjmlp
> It was not a replacement for C.

Sure it was for Bjarne, that is why he created it in first place.

After being forced to re-write his thesis from Simula to BCPL, he swore never having to deal with such low level languages again.

C with Classes was his solution to not having to write C directly, after he got his job at AT&T.

humanrebar
It's true that generative programming can make up for shortcomings of C. But you're pretty much writing in two languages at that point, C and whatever spec generated the rest of the C code. It's not an apples-to-apples comparison to C++.
khitchdee
Well, some parts of the generative programming could be built into a tool and you probably wouldn't have to rewrite a generative program each time. So it's not really writing in 2 languages but using code generation to assist the programming process to reduce potential for error as a more flexible alternative to creating fixed constructs in a purpose built language.
humanrebar
You can get 90% of that benefit by using snippets in your favorite editor. I guess you could consider that "code generation", but "generative programming" means, to me, "check in the specification, not the production code".
khitchdee
You're assuming gnerative programming is used to completely replace direct programming. This doesn't have to be the case. It could also be used merely in an assistive role to supplement the ability to write code.
humanrebar
I'm not. That's what I'm referring to as "snippets", though other forms of scaffolding do apply. If your position is that people should use more sophisticated editing/authoring tools on a regular basis, that's not that controversial a statement.

I was just saying that full-blown code generation isn't merely writing in the same language but adopting a DSL as well, so we're not strictly comparing languages at that point.

khitchdee
Right. Code generation has typically been associated with DSLs.

Here's one way it could be done simply. Let's say you wanted to automate the process of memory allocation and deallocation. You would need a way to describe to the code generator the mepory requirments of your structure. For that you would need a description outside of C. But that description could be embedded into the comments of your code and your code generator be designed to parse those comments to determine what needed to be done.

Knuth also came up with the idea of Literate Programming in which the description of a program is embedded as Latex in the code. This could work in a similar way. So, while you would use a DSL, the description would be inline with your code so the authoring process would be integrated and not 2-stream.

pcwalton
> D, Rust, OCaml, and a few other projects are interesting in this space since they provide some of the same benefits as C++ with respect to correctness and safety.

Can you name a correctness and safety benefit that C++ has that these programming languages do not?

red75prime
Probably there are no such benefits. But taking the less serious approach, LLVM's -fsanitize=undefined could be thought of as the one.
humanrebar
I didn't mean to imply that C++ was safer somehow. I just meant that those languages are also competing in that feature space in a way that C doesn't.

And, on a pedantic level, C++ competitors can't provide exactly the same benefits of C++ because they took different approaches.

What's a key design difference among these languages? Well, C++ can mostly just #include a C header file and go with it. The other languages provide FFI mechanisms, but they each require declarations of the FFI to match the compiled C code. So theoretically there's a little more room for errors in that translation, though I doubt that's a big concern on the whole. Each of those languages have more mature module systems, which should more than make up for keeping FFI interfaces in sync with C headers.

WalterBright
Over in D-land we've embraced the concept of using D as a "better C" :-)

https://dlang.org/blog/2017/08/23/d-as-a-better-c/

This is not in the sense of tossing away C coded programs wholesale and rewriting it in D, but incrementally using D here and there for parts of a C program. That way, you've always got a working, usable program.

harry8

    if (existsCoffee)
        writeln("Drink coffee");
http://ddili.org/ders/d.en/if.html Sad that you adopted one of C's worst features. Why? Can you get rid of it and mandate the bracing every block?
WalterBright
My take on C's biggest mistake:

https://digitalmars.com/articles/b44.html

harry8
Sure but there is just no reason at all to copy unbraced blocks. All you do is invite bugs for zero benefit.

Maybe there are bigger issues with C? But that's a different discussion. I want to know why you copied something as simultaneously horrendous and useless as unbraced blocks? If you just didn't think it through and that's the way languages syntactically similar to C have always done it, ok. I'm sure I've made worse mistakes. But please call it one way or the other.

Aug 23, 2017 · pjmlp on D as a Better C
And on embedded even C++ hardly managed to overtake C.

https://youtu.be/D7Sd8A6_fYU

None
None
Sep 25, 2016 · 86 points, 124 comments · submitted by adamnemecek
gravypod
The problem with C++ is the constant introduction of unneeded features that are infinity obscure in necessity.

People will say "Oh just don't use that feature" but that's not how this works. If something is there it is used. In reference to C, I don't think I know of a single feature or release that had major changes in how I wrote C. Maybe C99 and allowing me to declare in a for loop.

I've been using C++ for class this semester and the only thing I like is reference types. Makes pointers much more concise. Other then that it can all go in the bin. In order to keep my C++ project clean I've needed to avoid a huge set of features and keep it in a data-oriented design.

sseagull
I've been using C++ for a long time (10+ years). At one point (around C++11), I decided to really embrace the advanced features (template metaprogramming mostly) and stop trying to make the language something it wasn't.

It can be complicated, for sure. But there is a certain plesantness that comes with letting the compiler do a lot of work for you. It can almost be like the switch to python - just let the compiler figure stuff out.

This results in a lot less duplicate code, etc. The cost is some pretty bad syntax and compile time, though.

Try to keep an open mind

gravypod
I mean I've been programming for some time and I come from a strong Java background. I get the basis of what C++ is trying to do with their new features but I think it's horribly executed when looked at in comparison to other modern languages like Java and Rust.

Speaking from a very strong Java background after Jigsaw I think Java will outdo the generics capabilities present in C++ in every way. Java 9 is bringing some crazy features to the mix. From what I understand they are getting rid of the boxing to object from generics to keep types static through lists and other generic elements. That's amazing and something C++ still does as templates are basically massively duplicated code in your binary while the JVM will get this for free at runtime.

Rust is also just out of left field as they are doing amazing things with their "cost-free abstraction"

hackits
When I think about features in C++ that I would love to have in C, the only thing that comes to mind is constructors and deconstructions for RAII.
Koshkin
Problem is, using destructors (and RAII) may have, in general, certain performance implications that C may not be willing to deal with. This is somewhat similar to demanding that C had a garbage collector built in. Note that, being lazy, memory management by means of garbage collection may turn out being more efficient than using the (eager) destructors.
hackits
Don't see how there could be any performance implications with having RAII within C. It would be a simple method call with the this pointer to the struct during complication. Though if your performance consideration is at the assembly code level why use C?

I've had some good/bad experiences with garbage collectors. They do help improve productivity and ROI within the enterprise space where memory isn't too much of of issue. Then when memory does become a issue within smaller memory footprint environments they can be a real pain in the ass.

gravypod
If anything this video shows us that there is probably a lot less of a performance hit actually is take.

That's one of the things mentioned in the source video.

gravypod
My issue with RAII is that it's fundamentally not what you expect to happen.

If I say:

  int i;
I don't expect that to create an integer. I expect that to reserve memory in the program's space for an integer.

In the same way I don't expect this to call malloc:

   int *i;
I just expect that to hold the space in the program data where and int pointer can be stored.

Furthermore I don't expect this to run any code (just as the other two).

   string s;
I don't expect that to construct anything, that's just a place for me to put data. This way, we know not to use data before it's initialized.

In C++:

   int i;
   if (i > 10) printf("Greater then 10\n"); 
Is that going to always work how we expect it?

How about:

   string s;
   if (s.length() > 10) printf("Len is greater then 10\n");
That is going to always work how we expect it since it was constructed.

This is fundamentally different then uninitialized integers or primitives so I dislike it's use.

I strongly dislike the use of this term but it in my mind is an "Anti-pattern" as it promotes two separate ways of thinking about variables that are fundamentally completely different.

Info taken from:

http://www.cplusplus.com/reference/string/string/string/ http://www.cplusplus.com/forum/general/67249/

Now I'm no expert in education but this knowledge has taken me years to learn through my life and I don't think I'd have been able to do it if I didn't LOVE computers and programming.

I don't know how someone would think that this is good behavior because of it's inconsistencies between two outwardly similar cases.

jonstewart
I think part of your expectation may be coming from Java, where only fundamental data types are stack allocated and everything else has reference semantics to heap-allocated objects.

For the sake of syntactic consistency, one could argue that C++ should mandate "()" as a suffix to declarations to invoke the default constructor. However, what good is an allocated object that's _not_ constructed? For many classes, of course, the default constructor is trivial, but for others it isn't. The purpose of the constructor is to provide invariants that the code can rely on--it isn't obvious to me what common use case you could consider for an object that's allocated on the stack but not constructed, and it seems like it's asking for trouble.

Also, since C++ inherits C's syntax and semantics for fundamental types, "int i;" must be legal. So we cannot abolish the form.

hackits
Hi gravypod.

It depends. Oh I hate that word.

When I see int i; without context I don't know anything about where memory is allocated.

It can either be the following. 1) Stack allocated 2) Heap allocated 3) Is in the read only data segment.

Just starting with a int, it can be any of the above three, two that reserve the memory on the heap/stack and another that is only a read only part of memory. The heap is the only place where I would need to call malloc/free.

Though for most common libraries when I see string s; They mostly have a pointer null terminated string in memory, and the primitive data types residing as the member's of string.

RAII helps in the situation where instead of having to do tedious code such as.

String s; allocate_string(&s);

// do something with string. free_string(&s);

It can all be done via a standard convention of calling the deconstructor or constructor to initialise and free itself.

gravypod
Isn't "It depends" part of the problem?

For instance my professor when explaining to the other students why we use context-free grammars for parser he said "we always want a language to work how we tell it to. An if doesn't mean something different depending on where it is"

While I do agree that he is incorrect and that is a very close minded, and out dated, view of language design he is accidentally correct in another sense.

I'd like to ask "why" C++ chooses int i is different based on the location. I know the answer myself, but my peers don't and probably wont until years of pain in industry while parroting the same nonsense that C++ is the best language same as all of the other loons who think that there is a "best language".

Why is it ok for struct packing, for aligning data, and for initial memory state to decide how the program behaves?

In C++ it does, in C it's more sane but it sill happens.

> RAII helps in the situation where instead of having to do tedious code such as.

How is:

   string s = "";
and

   int i = 0;
Tedious? That seems like the sane alternative as it puts the behavior in the hand of the programmer. In nearly every language this is decided as the preferred way of allocating variables. Define AND assign to create something useful.

I don't think I understand how adding more case-specific behavior that doesn't apply to everything should be considered sane. It's more edge cases that aren't needed.

It's much simpler to say "we are just going to hold a slot in memory for any object, you need to initialize it" or to say "we are going to have default initialization for EVERY object even primitives" but it's horrible to say "we're going to do a combination of both and you have to figure it out"

KKKKkkkk1
The other thing about C++ is that you start by saying "I'll write C and only use this one extra feature from C++." and thereby you open a Pandora box. You decide to use reference types, and all of a sudden your classes are not default-assignable.
gravypod
I just don't use classes. I'd like to but again it's just not a good idea.

I also don't like default constructors see my other post as to why I think they are not reliable behavior to the programmer if they don't have experience in the language.

Again I didn't lie when I said "I am using C in C++" as I am using C in C++.

jonstewart
The problem with posts about C++ on Hacker News is that people who aren't experienced C++ programmers (you've been using C++ for a semester? do tell) feel compelled to write posts explaining the problems with C++.
metaobject
This problem is not limited to HN, I see it everywhere. And wrt to the notion that every feature of C++ (from simple, to complex, to highly complex) will be used, I've been using C++ professionally for ~13 years and there are certain features I've chosen to stay away from since they don't add any benefit to the problems that I solve (or to the way I solve them). And I feel fine about that bc I'm very pleased with the performance and abstractions I can create with C++.
MereInterest
As somebody who is relatively experienced with C++, but primarily on small projects with few developers, which features do you tend to stay away from?
Koshkin
I found it helpful to think about (the modern) C++ as a combination of two languages: one is a relatively straightforward language for application development, almost on par with Java or scripting languages such as Python; the other is a very sophisticated tool for implementing universally useful, generic classes and libraries.
gravypod
So my opinion on the difficulty of learning features in a language are not valid since I'm just learning the features?

Bravo.

My problem is not with what I think you are attributing to me but rather other issues with the language and tool chain. There seems to me very little that can be done in C++ that can't be done cleaner in C.

It's evident that most people who use a language aren't going to have time to spend years becoming a master at it. They are going to join a team and say "So to do my assigned task I need to do X, what features let me to X the cleanest" and this is how I've taken on learning C++.

Sadly, no features that are new have yielded themselves to any problem I've seen. I haven't encountered it.

Your solution to rebut my argument is that "you need to be at least 10 years into the language to know anything kid!" yet you provide no rebuttal.

Please do provide an argument not an insult at my age the next time you'd like to raise a disagreement with my ideas.

Koshkin
There are many insightful comments in this thread (as well as others) that may provide arguments you are looking for.
gravypod
I've been reading some of them through and some of them are actually fairly well rounded. Let's see how they respond to the questions I've posed to them.

I'm specifically interested in the RAII question to see how they justify fundamentally different behavior for syntactically similar code.

Koshkin
You seem to dislike the idea of the default constructor, not RAII. Default constructors, at least for relatively simple types, are meant to be minimalist so as not to incur any significant overhead. Which makes them comparable in this regard to the "default constructor" of 'int'.
tossaway1
Well you didn't express your criticism a the reason C++ is difficult to learn, you described it as "the problem with C++" and it sounds like you don't have enough familiarity with the language to make that sort of assessment.

C++ isn't a great choice for many purposes, but for some purposes it is the go-to language - and for good reasons, not just because of inertia as some like to suggest.

As with all forms of craftsmanship, you need to choose the right tool for what you're trying to accomplish.

gravypod
Here is why C++ is difficult to learn. It's like my experience of dealing with Java's inherited state except at every point in the language.

For people who have never touched java's inherited state from extending abstracts or base classes please don't fall into the traps I did. I was writing a redundant networking library that was meant to load packets on the fly so I had some cleaver "c++ level" abstraction written out for it. It only made sense to me because I relied on horribly complex features of Java. I'd say the most complex feature of Java.

Read through this to get an idea of what's going on. You'll notice that this is one of the sections with the least detail in the entire Java Primer thing. This is because in my opinion even the Java developers don't know all the rules.

https://docs.oracle.com/javase/tutorial/java/IandI/multiplei...

Now I don't think I know these rules either. I spent 2 months sorting out this mess and ended up with a polished product. But guess what? I could never go back there and fix something "quick". I'd need to do a bit of reading, read through my source, experiment a bit. This is not productive nor good standards and because of this I try never to rely on inherited state in Java anymore.

The same goes for every pain point of C++. Sure an expert, someone who lives, breaths, and dies by C++ might know exactly what is going on from the get go but that can't just be the assumption for every programmer. It is my opinion that if a language designer expects someone to read up on the language before going in and changing things they have failed at one of the cornerstones of language deign and implementation.

Everything should be "of course" levels of ingenuity but in C++ everything is "what the fuck".

For instance, please read my comment on RAII.

You can also take the multiple inheritance problems I've had in Java and directly apply them to C++.

You've also got strange behavior, when coming from C, for dealing with strings. For instance, where does an std::string get allocated? Is it on the heap or stack?

For instance am I opening myself up to bugs by doing this in my latest CS lab?

https://git.gravypod.com/gravypod/school/blob/master/cs280/h...

There's no apparent flow or rhyme to anything in this language. It just seems to be complexity bolted on simplicity and called "an industry standard".

Also operator overloading. I'd say it's a great thing for defining numeric and mathematical constructs that actually implement the specific operators as you would expect. For instance speaking as someone who has implemented their own basic physics library in java that is a godsend. But why, in the name of god, would you ever think of using numeric operators on non-numeric constructs? That's just inconsistency again leading down the further train of C++ needing to be learning in full before used.

Further, namespacing is taught poorly. I've had to do my own reading and settle on a standard that I think is semi-sane at least.

Rather then using the entire std namespace the same as my class I've settled on specifying namespaced elements I want to use. This is not how anything is taught in any college I've examined.

An example of what I do:

https://git.gravypod.com/gravypod/school/blob/master/cs280/h...

What's the point of using a namespace if you are just going to blanket import the entire namespace? Also if that's not the SOP for industry why is it taught as such in college?

There are many many if-ands-and butts about C++ and I can't go into all of them as I don't know all of them.

I do like reference types though, that's nice.

jonstewart
You've admirably demonstrated the willingness to ask questions and learn in this thread, so I will try to rise to the occasion. I'm sorry to have been dismissive with my original comment... please understand that C++ takes a lot of abuse from inexpert programmers on HN. For example, I never would criticize Ruby without spending more time than a semester's class using it.

>> string token = "";

No, you aren't opening yourself to bugs, but it's unnecessary. A default constructed string is already == to "", token.empty() will return true.

get_token_type() should likely take a const reference to the string, as all of the operations on the argument are const. I saw elsewhere in the thread where you said you've avoided const so far. Honestly, const may be C++'s greatest feature; it is far, far stronger than Java's "final" (or Scala's equivalent "val").

Looking over this code from a high level, I'm not sure why you have get_token_type() with a string parameter and a char parameter, when the former just forwards to the latter. Couldn't you have a second char variable, "prev_char" or "last_char", in get_next_token() and then detect when the type of it differs from the current char. Then the only operation you'd be doing on the string "token" is appending to it. I could be missing something, though, as I've only taken a quick glance through the code.

I would generally agree with you that C++ is poorly taught almost everywhere. I think it was a win for CS departments when they transitioned from C++ to Java for introductory courses (and now many are transitioning to Python, also a win). I am fairly convinced that C++ programming is a craft and is therefore best learned under an apprenticeship model, of routine practice with expert review and guidance, coupled with some self-study.

_yosefk
As someone who's had to deal with C++ since the last century, I find that one problem with C++ is that people who aren't experienced C++ programmers can't get shit done, especially in a code base where experienced C++ programmers have demonstrated their erudition and knowledge of C++ arcana in all its glory. In fact, the intersection of people who had the patience to learn enough C++ to get shit done and people who also have the patience or basic desire to actually get shit done (as opposed to programming wanky wrappers and stuff) is annoyingly small (this however is not true everywhere, I'd expect no such problem to exist with game programmers, for example.)

The fact that a language is terrible for newcomers is a real problem, and a newcomer is a very good judge of that even if they aren't a very good judge of other aspects.

Especially loathsome are those people who teach, say, undergraduates majoring in physics some C++ as a way to introduce them to programming. You might think that someone who manages to deal with the math needed to do physics would be able to absorb C++, and often you'd think wrong; one physics undergrad told an experienced programmer after trying to understand what the fuck cout<<x actually does, "your head is full of garbage!", by which he meant that the amount of completely arbitrary rules that you need to memorize was not something that dealing with math and science prepared him for.

From the above I conclude that people who have a semester's worth of experience in C++ might not be C++ experts but they certainly know enough to burn the instructor who chose C++ in the first place at the stake.

sseagull
> what the fuck cout<<x actually does

I'm not sure where that conversation would go. It prints to stdout. Would the student say the same thing about printf("%d", x)? How far down the rabbit hole did he want to go?

Stream insertion syntax os pretty bad, though, I'll agree with that. Especially when you want to print floating point.

gravypod
The conversation then shifts to how it does this? What if I want to print to something else? Why if I want to read differently from a stream?

When you provide a shorthand that's all well and good but when you TEACH a short hand it's what's ONLY used by the students.

The students will assume there is no other way to read and write then using >> and << which is horribly incorrect. These are largely inadequate measures for reading and writing in my experience as you probably want to do formatting which printf just does better.

So many of the students in my CS class this semester can't do the first lab, which in all essence, is a tokenizer because they don't know that there are other ways for writing to, or reading from, a stream!

A short hand should only be used in a majority if it can do everything the long hand way can do.

Also for anyone interested what my first C++ project looked like you can see here:

https://web.njit.edu/~gwryan/CS280/CS280-Program-1-Fall-2016...

https://git.gravypod.com/gravypod/school/tree/master/cs280/h...

It's not my best work, but if any C++ people want to notify me of things I'm doing that's wrong I'm more then happy to learn.

sseagull
I will agree with the point that the other methods of reading/writing from streams aren't taught early enough, and that formatted output is pretty bad with streams. I've actually written a wrapper around snprintf for printing in c++ (I should put that on github sometime)

Your project looks good. Two minor observations: 1.) You have 'using' statements in a header file. This is fine for a small project, but is considered bad form in larger projects (every file that includes that header will end up including the 'using' statements. This can cause collisions in large projects).

2.) Const correctness is a good habit to get into. (Ie, only pass non-const references if you are actually changing the object in the function)

gravypod
I wasn't sure how const worked in this language so I decided not to mess with it yet.

Coming from Java I have a blanket policy that every variable is final unless needed to be modified. I've run into those pain points.

Your first observation is one I have some into as well but I haven't been taught how to do this.

For example if my header file needs to define the method:

   void test(std::string something);
Is it bad form to them define the header in my cpp file as such?

   void test(string something);
Isn't that also bad form? Coming from C some things like this could be done but very much shouldn't have been done.

I know for a fact that namespacing is one of the hugest benifits to large projects I just don't know how to use the tools provided by C++ to do it correctly. Java? Yea I can get anything you want nice and tucked away. But C++ with the way headers and namespacing works its difficult to obviously see what I want to do and how to get it done.

Any examples?

jonstewart
I'm not sure I understand the question completely. Do you mean "declare" instead of "define" in "if my header file needs to define the method"? Or are you asking about declaring the parameter to test as "std::string" in the header but then only as "string" in the .cpp definition, because of the presence of a using statement?
MichaelMoser123
> trying to understand what the fuck cout<<x actually does

You can always do fprintf instead of that; i almost never do C++ streams for io - there is always a way to avoid them.

gravypod
I have also never seen a codebase that has used cout piping that was worth any salt.

But then why is it the first thing we shove into peoples faces when teaching them the language?

MichaelMoser123
i think they want to make an impression: C++ is supposed to be a new language, and not just C with a class system + templates bolted on top of it. i guess streams is supposed to be the new way of doing IO, never mind the circular inheritance mess and virtual function calls for getting new data.
pjmlp
I was part of the C++ teaching group on CS labs on my university back in 1999.

The majority of them surely were able to get shit done in C++ at the end of the semester.

_yosefk
Was it their first language though, and more generally, what did they already know?

Don't get me wrong, I remember the people who taught me C++ rather fondly. It's just done really terribly really often.

Koshkin
I agree. To truly learn and appreciate programming, you have to be able to enjoy it, first and foremost, and, unlike, say, Pascal, Python or JavaScript, the languages like Java, C, and especially C++ make that extremely hard for a novice programmer. This is because before you even begin to appreciate the ideas based on which those languages were designed and the languages' sophisticated features, you need to face the problems that these languages are trying to solve, and that takes time and programming experience.

It may sound strange, but I find assembly to be an appropriate language to learn programming. Not only your focus will be on what you are doing rather than on the language itself, you will get a feeling of what is really going on, and you will quickly appreciate - and fully understand - the the reason why C is useful and that it is a good, well designed programming language. (In the same way, with enough experience using C, one comes to appreciate C++.)

partycoder
C++ is really hard. I have learned enough about it to understand that there's a lot of idiomatic ways of achieving things that I do not understand, especially with the latest standards.

When someone claims to know C++, especially in a recruitment context, I tend to challenge that, since it's really hard to actually believe these days. Some people claim to know C++, but basically just write everything as if it was C.

TickleSteve
C++ is not one language... there are many styles, for example:

- 'C with objects'.

- 'Everything is a template'.

- 'Embedded C++' (its a real standard, google it).

- functional.

- 'modern'.

(thats not a complete list either).

Each one of those is technically the same language, but they're all using a different subset of features and are almost unrecognisable from the rest.

partycoder
It is one language. Many of those subsets are not mutually exclusive.

Regardless of what your preference is, if you claim to know C++ you need to at least know some of its basic features, such as references, streams, templates, STL, etc. (features that have been around for a long time).

And if you claim expertise, to at least be familiar with basic features from the new standards.

dunkelheit
Your list of common features is a bit too broad. For instance a common sentiment among game programmers is "STL is shit, you better don't touch it at all".
caseymarquis
What's the reasoning? I haven't regularly used c++ for ~8 years, but I know the basics. I thought the downside to STL was increased executable size? If there are no generic constraints I can imagine issues popping up; effectively using generics in .NET often means using a non-generic abstract base class, building the generic class on top of that, and then constraining the generic type to the abstract class. A pain compared to Java, where you have runtime type erasure, but worth it IMO for the better reflection. I figure there's some similar quirk/gotcha in c++?
dunkelheit
I guess the main gripe is performance. Using STL containers involves lots of implicit heap allocations and copying things around (this last thing should have improved after the introduction of move semantics, does anyone have any numbers on that?). Most of the times performance is perfectly acceptable but a few cases when it is not + inertia can give rise to this anti-STL sentiment.

Here for example std::string takes a beating: https://news.ycombinator.com/item?id=8704318

Scea91
If you claim expertise you have to be more than familiar with the basic features. Thats not expertise.
partycoder
Strictly speaking, that's true.

But in terms of knowing the latest features, it might be hard to keep up with the latest developments in C++, especially since even if a standard is released, it takes some time for compilers to implement them.

TickleSteve
true, they're all overlapping subsets....

The point being that the way you structure your software in each of those styles is very, very different.

They're all idiomatic C++.... just different idioms.

In fact, thinking about it, thats what it is...

C++ is a multi-idiom language.

ratboy666
Sure, with an execution model that is so complex that it takes scientific experimentation to determine the /best/ (in terms of execution speed) to write code to manipulate a simple memory mapped device. (This, from the lecture).

That is so complex, it is the only language that I need the language at hand to read someone else's code. Not a library reference, a /language/ reference.

Indeed, I am maintaing one C++ application. This is a wrapper for CEF3 (https://cefbuilds.com/). This is the Chromium browser as a library. I have to support the library and wrapper on two platforms: Linux 64 bit and Windows 64 bit. Note that the usual Windows build uses the Microsoft C++ compiler. But, I am uses mingw. This requires source code edits to compile! I blame the complexity of the language.

Indeed, C++ is so difficult that the shop I work for (which is, by the nature of our product, very conservative) has gone to Java instead.

TickleSteve
Platform API differences != language complexity.

These are two different things, platform differences are normally handled by a simple abstraction layer (or ifdefs if you're into masochism).

pjmlp
We did the same in 2006, and are mainly a Java/.NET consulting shop nowadays, but I still use C++ on side projects.

Given language difficulty, while I hope never to maintain C++ code that makes use of SFINAE, Java's simplicity is misleading.

The language might appear simple, but mastering the whole Java eco-system (JSE, JEE, Spring, embedded, Android, features per JDK version), performance monitoring tools, commercial JDKs and IDEs, isn't that easier either.

satysin
There is nothing "simple" about Java once you get past the basics. When you get into the EE world it gets extremely complicated.
pjmlp
Which is exactly my point.

Also the reason I argue that those that think Go will be kept simple, just aren't prepared for the eventual mainstream enterprise adoption.

Imagine when IBM or similar, releases their vision of GoEE.

satysin
I think Go depends in if Google want to take it from a language that solves their problems well to one that solves generic enterprise problems.
qwertyuiop924
No.

There's everything simple about Java. The semantics of Java are actually pretty simple, at least compared to C++. What's complicated are the monstrosities people build with Java, but those aren't inherent in the language.

Saying that Java is complicated because EE exists is like saying that C is complicated because Linux exists: Complexity can be built atop simplicity. And for some reason, Java is a complexity magnet.

pjmlp
> The semantics of Java are actually pretty simple, at least compared to C++.

While true, have you ever tried to answer Java Puzzles?

qwertyuiop924
It's not Lisp, but OTOH, C++ doesn't need puzzles: Template Metaprogramming, as well as many other parts of the language, are already one. And god help you if multiple programmers on a project use different subsets of the language...
MereInterest
I would say that the complexity of a language and the complexity of programs within that language are inversely correlated. Java is a very simple language, but as a result, the programs written in it must be more complicated to make up for the shortcomings of the language.

As an example, Java's lifetime rules are much simpler than those of C++. At some point after all references are gone, the object will be garbage collected. Simple. But as a result of this simplicity, you don't know when the finalizer will be called. You can't use it, for example, to flush and close a file, because you don't know when file will be closed. Instead, you need to use try/except/finally, and so you can't add this to an existing class, because it would require code modification from all the users of the class.

Up until Java 8 and lambda functions, functions could not be passed as arguments to other functions. Therefore, the developer needed to make an entirely new classes derived from "Callable". Complexity that came from the simplicity of the language.

C++ has a lot of complexity in the language itself. I won't deny that. What I will argue is that the complexity of the language enables simplicity in programs.

Edit: Lambda statements came in Java 8, not Java 7.

sebcat
> Up until Java 7 and lambda functions, functions could not be passed as arguments to other functions

Wasn't lambda expressions introduced in Java 8?

MereInterest
Whoops, my bad. Edited.
qwertyuiop924
No, not really. Complexity is not about the language: It's about how you use it. It's not necessarily Java's featureset that makes it so complex, it's its idioms.

C++'s lifetime rules, on most variables, are this: It's allocated until you say it isn't. Some of the vars might be refcounted or GCed, but with GC you've still got the same problem on your hands as finalizers, and refcounting can't handle cycles. Manual memory management is dramatically more error-prone than finalizers ever were (unless you're using RAII, but that's not entirely idiomatic, and cannot be).

As for functions not being able to be passed as args, that's not simplicity, that's a straight up limitation. What makes a language simple is uniformity, simplicity, and consistency. Java has a good deal more of all of these than C++

Complexity in the language doesn't enable simplicity in programs, though, because now your program has to deal with 6000 different special cases.

In any case, Lisp and Scheme are possibly the simplest languages, and are celebrated for their power, clarity, and the simplicity with which they can express programs.

MereInterest
I'd be interested to hear why you say that RAII cannot be idiomatic. With `std::unique_ptr` and `std::shared_ptr` for handling pointers, `std::vector` for handling data arrays, `std::string` for handling char arrays, I would argue that modern C++ is very heavily RAII. At this point, if I have a class that cannot be declared on the stack, with cleanup handled by RAII, I consider it to be a broken class.

Good point on limitations vs simplicity. I think that there are different forms of complexity. Some complexity is necessary, due to the nature of the underlying problem. Other complexity is incidental, being due to poor implementations. As an example of essential complexity, C++ has different declarations for stack-based variables and heap-based variables, while Java does not. This is because Java does not allow classes to be declared on the heap, and so it does not need an extra form of declaration. On the other hand, C++ definitely has lots of incidental complexity as well, mostly due to its long history. Having four different constructs for loops is incidental complexity.

I agree that the idioms are what make Java programs be complicated, rather than the language itself. What I'm not sure on is how much those idioms are needed to overcome limitations in the language, and how much they are unnecessary parts of the culture.

Oh, absolutely on Lisp. Lisp/Scheme are amazingly simple, and amazingly powerful. The one downside that I've found is that it doesn't correspond to the hardware as much. Much of C++'s complexity stems from trying to provide as many features as possible while still compiling down to reasonably fast code.

junke
> The one downside that I've found is that it doesn't correspond to the hardware as much.

The hardware keeps changing. What Lisp provides is a way to access low-level details when necessary, but with a default mode of operation that is managed (developer-friendly): GC, safety checks, arbitrary precision integers, etc. Like for all languages, a compiler can be told to try more optimizations if you want, and if you are ready to spend a little more work on it. In some implementations, you can extend the primitives known the compiler to emit better assembly code (e.g. https://www.pvk.ca/Blog/2014/08/16/how-to-define-new-intrins...).

qwertyuiop924
Well then, that's your problem: C++ is trying to be both low-level and high level at the same time. This isn't a good idea, IMHO.

What I mean is that while some amount of RAII is a common idiom in C++, It's rare for a program to use RAII fully, as many C++ idioms conflict with it. Mind, I'm not an expert, so I might be wrong, but that was my understanding. AFAICT, if RAII was used all the time, idomatic C++ would look a lot more like Rust.

pjmlp
> Well then, that's your problem: C++ is trying to be both low-level and high level at the same time. This isn't a good idea, IMHO.

It is a very good idea and C++ isn't alone there.

Professional Basic dialects, Turbo Pascal, Delphi, Modula-2, Modula-2+, Modula-3, Ada, D, Rust, Mesa/Cedar all share this idea that you can program at both levels, depending on the needs of the use case.

qwertyuiop924
C++ has less distinction though, and it's so huge that even Bjarne can't keep the whole language in his head. The net result is that many people use the low-level parts of the language for high-level work and vice-versa.
pjmlp
The same applies to the languages I listed, given the amount of years they have.

C++ main issue has always been C's compatibility and the C subculture.

The copy-paste compatibility was necessary to bring C developers over the fence to C++, with minimal changes to their tooling.

So C++ inherited all the flaws and UB from C.

Then many of those kept using C++ as plain C with Classes, which influences many of the design decisions regarding language semantics, specially given backwards compatibility as no one wants to repeat Python's error.

Having said this, although I enjoy playing with template metaprogramming, I hope never have to deal with SFINAE, declpspec and function return arrow syntax in production.

qwertyuiop924
...But that's not often how those languages are used.

And most of those "flaws" aren't flaws in C: They were deliberate design decisons. Arguably bad ones, yes, but they were made a reason. By C++, most of those decisions didn't have any reasons, or were actively against C++'s goals, if not C.

I know you hate C, but blaming C for C++'s problems is like blaming dogs for the monstrous dog demon that someone made with gene editing. C compatability was a bad idea, but you can't blame C for that. Also, it's overly baroque.

But yeah, I think we can all agree that complex TMP is kinda sucky.

pjmlp
Those decisions are documented in "The Design and Evolution of C++".
pjmlp
The main issue with RAII is that you can only do properly if as you say, the classes were designed to be stack allocated.

Also that no one just placed such class in the the heap, and it was missed, because no one is actually doing code reviews or making use of static analysis.

Another issue with best practices and ownership are binary libraries. There isn't any sort of control one can have over them, so they are the place where RAII and ownership just goes out of the window.

In any case this is much worse in C than C++, because at least C++ does offer some language tools to deal with it, however there is no rescue from developers using C with a C++ compiler.

> Oh, absolutely on Lisp. Lisp/Scheme are amazingly simple, and amazingly powerful. The one downside that I've found is that it doesn't correspond to the hardware as much.

Actually it can also be an upside, as you see with the adoption of FP patterns in mainstream languages, including C++.

One of the themes at CppCon was exactly hardware heterogeneity and possible C++ abstractions to take advantage of it, while keeping the algorithms high level.

qwertyuiop924
Pretty much exactly the point I was trying to make about RAII. Thanks for explaining better than I did :-).
MereInterest
I feel that the solution to both classes designed for heap allocation and binary libraries is the same: making a decent wrapper around them that obeys RAII. In many cases, this is just requires using `unique_ptr` with a custom deleter.

    auto deleter = [](unsafe_type* t) { cleanup_unsafe(t); }
    std::unique_ptr<unsafe_type, decltype(deleter)> safe(make_unsafe(), deleter);
If this is used in many places, you can make a very easy wrapper class to handle it.

    class safe_wrapper {
    public:
      safe_wrapper()
        : unsafe(make_unsafe()) { }
      ~safe_wrapper() {
        cleanup_unsafe();
      }

      unsafe_type* operator->() { return unsafe; }
    private:
      unsafe_type* unsafe;
    };
(Note that the example there is only for use within a single function. If the safe_wrapper is to be returned from a function, then the copy/move operators should be defined as needed.)

Certainly, when passing ownership back to the binary library, you are relying on it to correctly handle ownership. But so long as the ownership is in one's own code, you can easily add the type safety.

Regarding a stack-based class being accidentally placed on the heap, you can't prevent all errors, you can only make it less likely. I'd argue that it is easier to accidentally forget to call a cleanup function than it is to accidentally place something on the heap. With C++11 and up, any calls to "new" should be regarded with deep suspicion.

True on the FP patterns moving in, and I love them. `std::function` is a joy to work with, especially as compared to either C-style function pointers or inheritance from a "callable" type.

mlvljr
z-value-refs! Don't forget z-value-refs!
dunkelheit
This really starts to hurt when you go around shopping for C++ libraries. You can totally mandate a particular C++ style in an organization and achieve good results but good luck trying to use a library written in another style. Which is one of the reasons why C++ library ecosystem is relatively scarce.
hellofunk
What? C++ has a gigantic ecosystem for high quality libraries in a huge number of fields.
pjmlp
The same is true of any language with similar history.

Do you believe anyone knows Perl, Python, Ruby, Java, C#, Ada, Haskell, OCaml, VB.NET, F#, ... across all language versions, the whole standard library, and most used third party libraries?

One always need to focus on a specific domain.

daurnimator
FWIW, this is why I use lua as my primary language: it's the only language I can keep all in my head at once.
0xFFC
I would love to read about your experience with Lua. I always thought lua is for some limited things.
daurnimator
What sort of thing do you want to read? I have tagged posts on my blog: http://daurnimator.com/tagged/lua but that's probably mostly library release annoucements.
loeg
The obvious comparison is C — where it is common to know 95-100% of the language. (The 5% I'd pick is general disagreement about expectations of UB and "weird" pointers, like pointers to array types.)
pjmlp
People that don't write portable C code think that they know 95-100% of the language.

I don't miss the days in the late 90's, early 2000, writing portable C code across multiple compilers from each OS vendor, across all major UNIX flavours and Windows.

Many that think to master C, actually master C in compiler X targeting OS Y.

loeg
What a sweeping generalization. Perhaps. But it's certainly easier to master portable C than portable C++.
pjmlp
Yes, that is quite true.

However I prefer that pain, to the lack of strong typing that C++ offers over C.

But better would be to use something else instead of C and C++, more type safe, without UB and without the wide range of implementation differences and compiler extensions.

RandomOpinion
>Some people claim to know C++, but basically just write everything as if it was C.

Nothing wrong with that; that's not uncommon in embedded systems development.

satysin
I have been programming in C++ for almost 17 years now and I would say I know maybe 20-25% at most.

The reality of C++ is you know what is needed for the problem you need to solve. As people mostly work in the same (broad) areas for their day to day work it is unlikely you need to know outside of that scope regularly. At least not in my personal experience.

Also I strongly believe nobody truly understands C++ streams :)

blub
What are the components of C++ that add up to 100%?

I can count:

* language basics (variables, structural statements, functions, error handling, preprocessor, how compilation works)

* OOP

* functional programming (which is not that complicated at all in C++)

* generic programming

* advanced generic programming and metaprogramming

* the C standard library

* the C++ standard library basics (containers, algorithms, smart pointers, cout << "foo")

* more advanced c++ standard library (maths stuff, threading(?), chrono, advanced streams (not needed))

I think most C++ programmers have a reasonable command of all of these except the metaprogramming and advanced standard library.

AlexandrB
> * OOP

C++ OOP is an endless tire fire. I now have 7 years experience writing C++ "OOP" on the job and I still run into surprises when I try to do things that are easy in other languages but unnecessarily hard in C++. Plenty of examples in the C++ FQA[1].

[1] http://yosefk.com/c++fqa/inheritance-mother.html#fqa-23.5

blub
I'm not an expert at this, but it seems to me that it would be a good idea to take the time to learn it properly in one go instead of independently discovering all the mistakes that can be made in 7 long years and then being upset about it.
satysin
You just proved my point ;)
blub
Doubtful. What would 25% of the above list be, basics + OOP? No standard library at all? No templated code?

I am saying one can barely write programs by knowing just 25% of C++, let alone for almost two decades.

On the contrary, I think 80%+ of the language is accessible to every programmer.

AlexandrB
> On the contrary, I think 80%+ of the language is accessible to every programmer.

80% of the language looks accessible to every programmer. Until you hit some corner of C++ behaviour and you realize your mental model of what C++ is doing is woefully incomplete. C++ is stuffed full of syntax, and obscure interactions between that syntax will continually trip you up. Each of the things in your list is somewhat contained on its own but interacts in surprising ways with every other thing on that list.

For example[1], want to create a template friend function for a template class? Prepare for function definitions like:

    Foo<T> f<>();
Edit: that's not to mention various C++ idioms like CRTP [2] which don't fit neatly with the stuff you listed but are non-obvious and occur in a lot of complex C++ code.

[1] http://yosefk.com/c++fqa/templates.html#fqa-35.16

[2] https://en.wikipedia.org/wiki/Curiously_recurring_template_p...

hellofunk
> functional programming (which is not that complicated at all in C++)

> I think most C++ programmers have a reasonable command of all of these

These gave me a bit of a chuckle. It's true only if you've never done proper functional programming using a genuinely functional language.

It's true that you can now pass lambdas around as first-class values easily, store and manipulate them as you might in a functional language, and that's a fantastic convenience.

But that's not what functional programming is. None of the idioms you'd use in Clojure or Haskell are wise to use (yet) in C++ (although Niebler's Range library will make a big step in the right direction... in C++20, where it's currently slated for specification).

If you try to do real functional programming in C++, you'll end up with a very inefficient program that pales to writing an algorithm with a more procedural or OO idiom.

And, in my experience interacting with lots of C++ developers, most do not know what actual functional programming is all about.

blub
A discussion about "proper functional programming" is not particularly relevant, because the topic is functional programming in the context of C++.

The constructs that C++ offers for FP are not complicated.

hellofunk
Sorry, but this is just simply not true. If you've never done functional programming before, then I could see why you think doing it in C++ is not complicated. Here is an example of just how large the can of worms gets when attempting to bring functional programming to C++:

https://bartoszmilewski.com/2013/11/13/functional-data-struc...

and:

https://bartoszmilewski.com/2013/11/25/functional-data-struc...

And, I disagree that you can change the definition of a particular programming paradigm when discussing a particular language. Functional programming means something that is not really possible in C++. For starters, the fundamental underlying data structures for functional programming do not exist in C++ and there is no third-party implementation of them worth mentioning; the above experiment is admitted by the author to fall flat when doing anything idiomatic.

As I mentioned before, C++20 might turn the tide on this front a little bit, thanks to the Range library.

blub
Fine, what shall we call this programming style in C++ (lambdas, immutability, function composition, etc) so that everyone is happy then?

Functional style C++?

I haven't felt the need to go deeper than that, it's very possible that I've missed many interesting things, but it's not clear that I can use those things and see tangible benefits in my projects today.

faragon
In my opinion, many C++ projects would be simpler, cheaper, safer, and better maintained, if were written in C (with adequate libraries, e.g. for strings, vectors, maps, threads, timers, sockets, etc.).
papaf
I started converting picol to C++14 yesterday:

    http://antirez.com/picol/picol.c.txt
I have been programming in C++ for over 20 years and my version is bigger :-( Its nice not having to malloc/free but the moment I turned the structs to classes I was battling the bloat.

I still enjoy programming in C++ but there is a lot of truth in the criticism that programs written in C are simpler.

faragon
I've been writing C++ for more than 20 years, too. In perspective, I made some mistakes when choosing writing many C++ components that could have been better/simpler/cheaper in plain C, with some abstraction via libraries (e.g. because complexes of not being seen as "smart enough", etc.). Writing simple/compact programs is hard both in C and C++, although, from my experience, bloat comes much more from C++ (inlining, etc.).

BTW, Salvatore Sanfilippo (antirez) is a very sharp programmer, able to write programs without redundancy and look easy (which is very difficult to achieve).

knocte
facepalm
IshKebab
I guess you're joking, but just in case, C++ prevents entire classes of errors that are almost guaranteed in C projects.
faragon
I was not joking. Also, C++ introduces other classes of errors. There is no silver bullet.
sseagull
A vector/map of what? How do I have a map of some key to a custom structure? How do you do this simply without templates? Separate libraries? Macro hell?

How do you handle types which need to free memory without destructors? Manually loop over the vector and free stuff every time one goes out of scope? That doesn't seem safer to me.

faragon
>>A vector/map of what? How do I have a map of some key to a custom structure? How do you do this simply without templates? Separate libraries? Macro hell?

Separate libraries, without "macro hell".

>>How do you handle types which need to free memory without destructors? Manually loop over the vector and free stuff every time one goes out of scope? That doesn't seem safer to me.

Providing both heap and stack based allocation. E.g. allocating a vector in the stack would require no explicit de-allocation (example: https://github.com/faragon/libsrt). For heap allocation, you would need to call some sometype_free(&a) function, obviously (there is no RAII in C).

sseagull
Yes, but it would still be hard to support custom types, wouldn't it? Ie in your library, I would have to use pointers, which might be unsafe? Adding types to a library like that (like double) causes the amount of code to grow dramatically (maybe even n^2 for maps).

You're library does look nice for what it does, and may have to look into it for some projects (I do have some C projects). Thanks!

faragon
That library is still in beta stage, there are others.

For maps I've implemented integer, pointers, and strings, without code bloat (tree implementation is common, without macro-templates). I'm planning adding some generic type support for fixed-size elements, while keeping internal tree pointer-less and both stack and heap allocation possible, with minimal code bloat/duplication.

aksx
>For heap allocation, you would need to call some sometype_free(&a) function

i find '__attribute__((cleanup (fn)))' fascinating in C, need to try it in some production code though.

loeg
It's quite useful.
pjmlp
That is GCC C, not ANSI C.
FrozenVoid
Only a handful of modern C++ features appeal to me. In order to use them, i actually have to use other features(less desirable, like templates or class inheritance) which create bloat, latency and corner cases requiring knowledge of the inner structure of the things(like variadic functions actually being variadic template syntax sugar). Ease of use which C++ brings is 'balanced' by opaque and hard debugging, large executable sizes and large memory use.
KayEss
Can you give some concrete examples?
FrozenVoid
http://pastebin.com/fgPhGaxz
KayEss
Personally I think that looks pretty good. There's no templates, no inheritance. Not sure what would make bloat there nor latency. Whatever the faults of the syntax for folding, it's got to be better than VA_ARGS hasn't it?
FrozenVoid
Have you tried to compile and run it?
adsofhoads
There are templates: for example

    void print1(auto x){std::cout<< x;}
is a function template

    template <class T>
    void print1(T x){std::cout<< x;}
This is not valid C++14 however, so it doesn't compile. If you replace these, you'll probably still get a stack overflow while expanding the templates because there are almost 7000 arguments to a single function call.
KayEss
And that works if you use the old C style variadic functions?I suppose I see no reason why it wouldn't, but that isn't the same.
FrozenVoid
>This is not valid C++14 however, so it doesn't compile.

It is "valid C++" IF there are fewer arguments, like 6-10

The example illustrates C++ internal representation of "variadic functions".

adsofhoads
I was referring to the use of generic functions (ie. with an argument with type-specifier auto) which is not C++14. Your copy of g++ may accept it as an extension.
MereInterest
I feel like this is by design. `std::vector` is an amazingly useful thing, for example. But in order for it to exist, you need to have templates. `std::unique_ptr` handles memory management automatically in 95% of cases, but in order to do so, the language requires lvalue and rvalue references, to properly steal resources. Heck, destructors and RAII beat the snot out of Python/C# "using" statements or Java "try/except/finally", but it requires correct lifetime management of objects.

The complicated features are all there to support simple library use. On a day-to-day basis, the complicated features are hidden behind a library, and are rarely seen. When you need them to write the library, they are available.

KayEss
Scott Adams (Dilbert) has been writing extensively on persuasion for the last year or so, covering many of the same points Dan does. He has put together a reading list: http://blog.dilbert.com/post/129784168866/the-persuasion-rea...
swah
In his podcast episode with Tim Ferris he cites again Influence - by Robert B. Cialdini PhD
cturner
The backfire effect has had a lot of airplay. I've just now made a quick scan of the study, but not read in detail (https://www.dartmouth.edu/~nyhan/nyhan-reifler.pdf). I don't think the paper justifies its conclusion that "corrections [..] increase misperceptions among the group in question".

From the paper, "In other words, the correction backfired – conservatives who received a correction telling them that Iraq did not have WMD were more likely to believe that Iraq had WMD than those in the control condition." (https://www.dartmouth.edu/~nyhan/nyhan-reifler.pdf)

I don't think that connection flows. Rather, I see this: when you take people who have developed political opinions, and act in a way that suggests insult to their world-view, some will react with defiance/sabotage.

The study identifies the pre-existing political leanings of the subjects. Hence, background work has been done to understand a subject's political persuasion, and the subject knows they have been profiled for this.

Then they isolate an issue which some subjects will know to be contentious across liberal/conservative lines, and present the subject with a position. This act (focusing on a vulnerable issue and then preventing evidence that indicates a clear conclusion) alienates the project from the subject, and sets them up to be from a rival worldview. Some subjects, particularly the more politically-aware subjects, will be speculating on the purpose of the study. Then the study asks the subject to - essentially - calculate one plus one one on the issue, towards a conclusion that supports the rival worldview.

The people running these studies will be identified by the participants as members of the intelligentsia. That will have a bearing on subject behavior, and will further encourage defiance in some subjects. In my scan, I didn't see signs of effort made to disguise or water down the focus of the study.

jdmoreira
I'm still watching but it took an interesting turn at the 30 min mark :)
x0re4x
C++ Zealot Declares: C++ Declining In Embedded Because Not Enough Preaching To Resistant C Programming Infidels
hellofunk
I fail to understand why his discussion of the words "merry, marry, Mary" and photos of him with Biden and Obama had any relevance to this discussion. That was a very odd interlude in an otherwise fairly interesting talk.
None
None
JohnLeTigre
You won't convince me that c++ is as good as c simply by representing a plain old structure as a class or by talking about the type of arrays.

To me, data-oriented design is more interesting: https://www.youtube.com/watch?v=rX0ItVEVjHc

TempleOS
faggot
wott
After 20 minutes spent complaining that nobody listens to him, several minutes of diversion to come to the point that people are not rational because they favour world view and moral sense (characteristics that he calls 'emotional') compared to self-interest, and that he finds that dismaying.

Well, I am dismayed that one may consider prioritising selfishness and immediate interest as rational and prioritising global thinking as emotional, and not the opposite. And that is supposed to serve as an anchor to the following points. Well...

Now at 30 minutes and the subject of the talk was barely tackled. I am not sure I have the strength to inflict myself the remaining hour.

knocte
Thanks, you just saved an hour of my life :)
bischofs
It seems like the minutia and subtlety of many c++ features at the cost of simplicity and readability lend themselves to cocky, in-love-with-themselves developers like this guy (who tells us upfront he wasn't actually building anything embedded in c++?!).
HN Theater is an independent project and is not operated by Y Combinator or any of the video hosting platforms linked to on this site.
~ yaj@
;laksdfhjdhksalkfj more things
yahnd.com ~ Privacy Policy ~
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.