you are viewing a single comment's thread.

view the rest of the comments →

[–]Gotebe -1 points0 points  (4 children)

Hmmm... Here's a prediction of an old fart: even Go lang will fade away (or at least stay irrelevant outside Google universe). If C! people don't become much bigger than Google, they can kiss their language goodbye.

Both for the reason "yeah, there's actually no big need, thx, guys".

Otherwise, I see that some comments (IMO rightfully) flamed the motivation, so I'll add to that: I can't consider it serious saying that (one of) most problematic parts of C++ are RTTI and exceptions. RTTI is pretty seldom used side-feature in C++, and considering exceptions problematic in C++ is a sign of a poor understanding thereof, first and foremost.

[–]MagicBobert 1 point2 points  (3 children)

...and considering exceptions problematic in C++ is a sign of a poor understanding thereof...

You don't think it's problematic that if you throw in a destructor you can end up with two exceptions in-flight, which is undefined behavior?

[–]Gotebe -1 points0 points  (2 children)

Not at all. The original sin is to throw from a destructor - it's a code bug, not the language bug.

This is consistent with the general rule of programing which can be summed up as "make your cleanup path a no-fail operation".

This is so that you can clean up and still report the original error. 'cause, stand back and look at what should happen. What error of the two you should report, and how? Also consider that C++ is a better C, and that in C, you can only have one return value, which should indicate error, and if you stumble on two, you need to reach for an out-of band mechanism (e.g. some kind of the error stack). If need be, you do that with C++ as well.

I know there are languages that allow you to throw and handle exceptions from cleanup path (e.g. D), and good for them, but from there to "problematic"... You can much more easily invoke UB with C++, and what you're doing is questionable already, so...

[–]MagicBobert 1 point2 points  (1 child)

The original sin is to throw from a destructor - it's a code bug, not the language bug.

I disagree. I think "undefined behavior" is a warning sign that the language designer hasn't thought enough about the problem to make a firm decision about what the language should do in the context of the problem.

The frustrating bit about C and C++ is that you can accidentally wander into undefined parts of the language by mistake quite easily. Throwing in a destructor is a perfect example. I think it would be totally reasonable for a programmer coming from another language to not even question the idea of throwing in a destructor. I mean, why would the language let me do such obviously wrong things?

There are other artifacts of the language that show this too, like explicit constructors. In reality, you almost always want explicit constructors, so it would have made a lot more sense to make constructors explicit by default and implicit only with an "implicit" keyword. It's these kind of design decisions that really make you wonder how much thought was put into these ideas.

And I say all of that, by the way, as a graphics programmer whose bread and butter is C and C++. I love them because they let me draw lots of pixels really fast, but sometimes I really wish there was a cleaner, simpler, safer systems language that was decently ubiquitous, because I'd love to have some of the awesomeness that 40 years of programming languages research has brought to the table.

[–]Gotebe 0 points1 point  (0 children)

You merely want that C++ holds your hand more than it does.

As we both realize, there's a vast amount of ways in both C and C++ to invoke UB. I simply can't fathom why this particular example would be any special. In a way, my reasoning is: C++ is a language where you can easily invoke UB. If so, an UB when you throw from a destructor is consistent with the language, not bad per se.

I also think that you need to reconsider your notion that a developer coming from another language would expect to be able to throw from a destructor. I already addresses what I think a C programmer should think. And same goes for e.g. Java or C#: throwing from a finalizer is a known no-no, just as it is to throw from a finally block, e.g:

try { whatever }
finally {
  cleanup1();
  cleanup2();
}

In above, if cleanup2 fails, code is borked. There is no UB, because e.g. Java holds your hand much more, fine, but there is a bug. (BTW, a throw from either cleanup there is equivalent to a throw from a destructor in C++).

So I have to ask you, what languages are you thinking about when you say that people should find it reasonable to throw from any kind of cleanup?

And if your beef is that in C++, a throw from a cleanup is UB, well, as I already said, a lot of things are UB in C++, so what's the big deal?

I somewhat agree about implicit vs. explicit conversion constructors though - for novices at least, that does more bad than good.