Live data from Hacker News

In Defense of C++

dayvster.com

391–400 of 470 posts

Re: In Defense of C++

#391
post #235

A pet peeve of mine is when people claim C++ is a superset of C. It really isn't. There's a lot of little nuanced differences that can bite you. Ignore the fact that having more keywords in C++ precludes the legality of some C code being C++. (`int class;`) void * implicit casting in C just works, but in C++ it must be an explicit cast (which is kind of funny considering all the confusing implicit behavior in C++). C…

> It really isn't. There's a lot of little nuanced differences that can bite you. These are mostly inconsequential when using code other people write. It is trivial to mix C and C++ object files, and where the differences (in headers) do matter, they can be ifdefed away. > void * implicit casting in C just works, but in C++ it must be an explicit cast (which is kind of funny considering all the confusing implicit beh…

I was not trying to be exhaustive.

And I think you're downplaying many of the ones I mentioned, but I think this level of "importance" is subjective to the task at hand and one's level of frustrations.

Re: In Defense of C++

#392

A pet peeve of mine is when people claim C++ is a superset of C. It really isn't. There's a lot of little nuanced differences that can bite you. Ignore the fact that having more keywords in C++ precludes the legality of some C code being C++. (`int class;`) void * implicit casting in C just works, but in C++ it must be an explicit cast (which is kind of funny considering all the confusing implicit behavior in C++). C…

> You can do it in C++, but sizeof(EmptyStruct) is 1. Unless you use the C++20 [[no_unique_address]] attribute, in which case it is 0 (if used correctly).

I completely forgot about that!

Re: In Defense of C++

#393

Earlier quoted context omitted.

I'd file that in the category of "what I can't recreate, I can't understand".

With that argument you could discard JavaScript because V8 is hard to understand. C++ giving you the ability to create your own containers that equal the standard library is a bonus, it doesn't make those containers harder to use.

That's a false comparison. There's a huge difference between a standard container library, and the combination of a (a) best-in-class byte code interpreter with a (b) caching, optimizing JIT, supported by (c) a best-in-class garbage collector.

I would argue that it's reasonable to say that creating a robust data structure library at the level of the STL shouldn't be that arcane.

Re: In Defense of C++

#394

Earlier quoted context omitted.

This is pure Stockholm syndrome. If I were forced to choose between creating a cross-platform C++ project from scratch or taking an honest to god arrow to the knee, the arrow would be less painful.

If you were forced to choose between creating a cross-platform project in one of the trendy language, but of course, which must also work on tiny hardware with a weird custom OSes on some hobbyist hardware, and with 30-year-old machines in some large organization's server farm - then you would choose the C++ project, since you will be able to make that happen, with some pain. And with the other languages - you'll pro…

> but of course, which must also work on tiny hardware with a weird custom OSes on some hobbyist hardware, and with 30-year-old machines in some large organization's server farm - then you would choose the C++ projectt, since you will be able to make that happen, with some pain.

With the old and proprietary toolchains involved, I would bet dollars to doughnuts that there's a 50% odds of C++11 being the latest supported standard. In that context, modern C++ is the trendy language.

Re: In Defense of C++

#395
post #262

Earlier quoted context omitted.

It's really not that big of a deal once you know how it works, and there are tools like CMake and IDEs that will take care of it. On Windows and OSX it's even easier - if you're okay writing only for those platforms. It's more difficult to learn, and it seems convoluted for people coming from Python and Javascript, but there are a lot of advantages to not having package management and build tooling tightly integrated…

I agree -- I've been at it long enough -- cmake etc makes stuff pretty darn easy. But in industrial settings where multi groups share and change libs something like debpkg may be used. You add caching and you can go quite deep quickly esp after bolting on cdci. One must cop to the fact that a go build or zig build is just fundamentally better.

Go build is fundamentally better? How so? Go build is so light on features that adding generated files to source control is a norm in go land.

Re: In Defense of C++

#396

A pet peeve of mine is when people claim C++ is a superset of C. It really isn't. There's a lot of little nuanced differences that can bite you. Ignore the fact that having more keywords in C++ precludes the legality of some C code being C++. (`int class;`) void * implicit casting in C just works, but in C++ it must be an explicit cast (which is kind of funny considering all the confusing implicit behavior in C++). C…

> A pet peeve of mine is when people claim C++ is a superset of C. It really isn't. There's a lot of little nuanced differences that can bite you.

> Ignore the fact that having more keywords in C++ precludes the legality of some C code being C++. (`int class;`)

Your very first example reverses the definitions of superset and subset. "C++ is a superset of C" implies that C++ will have at least as many, if not more, keywords than C.

Other examples make the same mistake.

Re: In Defense of C++

#397

Earlier quoted context omitted.

So, what programmers wanted (yes, already before C++ got this) was what are called "destructive move semantics". These assignment semantics work how real life works. If I give you this Rubik's Cube now you have the Rubik's Cube and I do not have it any more. This unlocks important optimisations for non-trivial objects which have associated resources, if I can give you a Rubik's Cube then we don't need to clone mine,…

In particular, move is important if there is something like a unique_ptr. To make a copy, I have to make a deep copy of whatever the unique_ptr points to, which could be very expensive. To do a move, I just copy the bits of the unique_ptr, but now the original object can't be the one that owns what's pointed to.

Sure. Notice std::unique_ptr is roughly equivalent to Rust's Option>

The C++ "move" is basically Rust's core::mem::take - we don't just move the T from inside our box, we have to also replace it, in this case with the default, None, and in C++ our std::unique_ptr now has no object inside it.

But while Rust can carefully move things which don't have a default, C++ has to have some "hollow" moved-from state because it doesn't have destructive move.

Re: In Defense of C++

#398

Earlier quoted context omitted.

std::optional does have dereference checking, but it's a run-time check: std::optional ::value(). Of course, you'll get an exception if the optional is empty, because there's nothing else for the callee to do.

> but it's a run-time check And that's the problem. In other languages that have a Maybe type, it's a compile time check. If your code is not handling the "empty" case, it will simply fail to compile. I honestly don't see any value in std::optional compared to the behavior pre-std::optional. What does it bring to the table for pointers, for example?

Nothing, but I don't think anyone uses std::optional. However, if you need to specify an optional integer, std::optional is much clearer than encoding the null value as a negative or other such hacks. Another use of std::optional is to delay construction of an object without an extra dynamic allocation. That's way more convenient than using placement new.

Re: In Defense of C++

#399
post #122
post #86

The article says "I think the biggest factor is that any rewrite of an existing codebase is going to yield better results than the original codebase.". Yeah, sorry, but no, ask some long-term developers about how this often goes.

It depends on the codebase. If the code base deserves to be a case study in how not to do programming, then a rewrite will definitely yield better results. I once encountered this situation with C# code written by an undergraduate, rewrote it from scratch in C++ and got a better result. In hindsight, the result would have been even better in C since I spent about 80% of my time fighting with C++ to try to use every l…

Data structures like maps and vectors from the standard library are still incredibly useful and make a fantastic addition to C if your focus relies on POD types, though if real time performance with heap cohesion is a problem then you’re right to go pure C

Re: In Defense of C++

#400

> Yes, C++ can be unsafe if you don’t know what you’re doing. But here’s the thing: all programming languages are unsafe if you don’t know what you’re doing. C++ can be unsafe even when you know what you're doing, since it is quite easy get something wrong by accident: index off-by-one can mean out-of-bounds access to an array, which can mean anything really. So, it's not that "all languages" are like that. That seem…

>So, it's not that "all languages" are like that. That seems like a "moving the goalpost" type of logical fallacy.

I think what's mean is that Rust's type system only removes one specific kind of unsafety, but if you're clueless you can still royally screw things up, in any language. No type system can stop you from hosing a database by doing things in the wrong order, say. Whether trading for that additional safety is worth it is IMO a more interesting question than whether it exists at all.

Personally, I mostly agree with you. I don't much care for traits, or the lack of overloading and OO, or how fast Rust is still evolving, and wish I could have Rust's safety guarantees in a language that was more like C++. It really feels like you could get 90% of the way there without doing anything too radical, just forbidding a handful of problematic features; a few off the top of my head: naked pointers, pointer arithmetic, manual memory management, not checking array accesses by default, not initializing variables by default, allowing switches to be non-exhaustive.

Post reply on HN