Live data from Hacker News

Modern C++ Won't Save Us (2019)

alexgaynor.net

21–30 of 266 posts

Re: Modern C++ Won't Save Us (2019)

#21
I used to write a lot of C++ (like 14 years ago at this point). I haven't really paid any attention to it in that time. I am looking at the code examples and what I see is a language trying to adopt features from Java, Rust and others - but where in those other respective languages there's like just 1 thing going on in a single line of code. In these C++ examples you have the namespacing stuff, templates/generics, implicit operators and constructor calls. It just feels like exactly what you would expect of a language like C++ to try to adopt the native features of these other languages. Which isn't a bad thing, but it just screams to me like wouldn't it just be easier to switch languages?

That all being said, I do get the "rush" C/C++ programmers feel when they write multi-threaded socket servers. You step back and go whoa - that worked?

Re: Modern C++ Won't Save Us (2019)

#22
post #19
post #6

Earlier quoted context omitted.

> The whole point of an optional type is to prevent accidental unchecked access to the value. You might argue it should be that, but it wasn't my impression that it is that. My impression was std::optional is just there to allow for representing the absence of a value. Ideally that should be zero-overhead, which means dereferencing it should degenerate into a normal object access. Hence the current design.

Do you mean that the purpose of std::optional is to be faster than a pointer (which could represent absence as nullptr)? I would have thought it would be ML-style safety, but it seems like you're right. I guess a tagged union (or std::pair ) would be faster—if the std::pair is a local variable, fields of the wrapped object will be at fixed offsets from your stack pointer or frame pointer, so you save yourself an inde…

No, the purpose wasn't to be faster than a pointer. You can't even necessarily use a pointer where you can use std::optional; the value of std::optional is embedded in itself.

One purpose would be type safety (and things revolving around that). Another would be to let you pass around an optional object just as easily as the underlying object.

As to whether it's a good idea to have it at all, I'm not particularly fond of it personally either. I don't have specific issues with its dereferencing safety though.

Don't confuse type safety with memory safety though. Type safety != memory safety != thread safety != ...

Re: Modern C++ Won't Save Us (2019)

#23
post #2

UB-invoking dereference in std::optional is such a baffling design choice. The whole point of an optional type is to prevent accidental unchecked access to the value. Sure, sometimes it's useful for performance to skip the check when it's already known-safe from the context, but such dangerous optimization should have been behind a method like `beware_of_the_nasal_demons()`, not an innocent-looking convenience syntax…

boost::optional was designed to mimic pointers. Before boost::optional, some programmers would return a T* as a caveman's optional. Boost wanted to preserve the syntax of *, ->, and operator bool. Dereferencing a null ptr is UB, so operator* for optional was the same.

I agree it would be nice if you could get an assert in operator*. But you can already fire up a debugger or sanitize build and get a nice error message anyway, so it's nbd.

Re: Modern C++ Won't Save Us (2019)

#24
My comment for too many years is that C/C++ fails to deal with three issues: "How big is it", "Who owns it", and "Who locks it". C++ has, with difficulty, made progress on "How big is it" through templates, but raw pointers keep leaking out. "Who owns it" has been tough to deal with, although "owned pointers" at least try. "Who locks it" has yet to be addressed at the language level, although at least there's now some agreement on multiprocessor semantics at the language level. The old line was that locking is an operating system problem.

After years of C++ and six months of Rust, I don't think C++ can catch up with modern languages with template gimmicks. Getting pointers right needs global analysis. Getting decent error messages about inconsistencies between point A here and point B way over there requires global analysis. Trying to build a borrow checker with the C++ template and type system is pounding a screw.

Rust has its own problems. Figuring out how to do something safely can be quite difficult. It can involve solving puzzles, and often involves rewriting things at several levels, especially when threads are involved. As a result, "unsafe" is too often used as an escape hatch when someone can't spend the time to get it right. Those who slave under the whips of "agile" may be forced to such hacks.

Re: Modern C++ Won't Save Us (2019)

#26
post #19

Earlier quoted context omitted.

Do you mean that the purpose of std::optional is to be faster than a pointer (which could represent absence as nullptr)? I would have thought it would be ML-style safety, but it seems like you're right. I guess a tagged union (or std::pair ) would be faster—if the std::pair is a local variable, fields of the wrapped object will be at fixed offsets from your stack pointer or frame pointer, so you save yourself an inde…

No, the purpose wasn't to be faster than a pointer. You can't even necessarily use a pointer where you can use std::optional; the value of std::optional is embedded in itself. One purpose would be type safety (and things revolving around that). Another would be to let you pass around an optional object just as easily as the underlying object. As to whether it's a good idea to have it at all, I'm not particularly fond…

All good points. Thank you.

Re: Modern C++ Won't Save Us (2019)

#27
post #24

My comment for too many years is that C/C++ fails to deal with three issues: "How big is it", "Who owns it", and "Who locks it". C++ has, with difficulty, made progress on "How big is it" through templates, but raw pointers keep leaking out. "Who owns it" has been tough to deal with, although "owned pointers" at least try. "Who locks it" has yet to be addressed at the language level, although at least there's now som…

I'm not sure what you mean by "global analysis," but Rust's borrow checker doesn't do any analysis that I'd consider "global."

Re: Modern C++ Won't Save Us (2019)

#29
post #11

It's interesting that one of the things C++ got right was having value semantics by default and most of these "problems" are the result of using either references or types that behave like dumb references/pointers such as std::string_view.

Value semantics as in "copy constructor for everything" is only helpful in limited ways. What is helpful is move semantics for anything mutable, which was introduced quite recently.

C++11 has been out for a decade now. Move semantics are not much more "recent" than Python 3.

Re: Modern C++ Won't Save Us (2019)

#30
post #27
post #24

My comment for too many years is that C/C++ fails to deal with three issues: "How big is it", "Who owns it", and "Who locks it". C++ has, with difficulty, made progress on "How big is it" through templates, but raw pointers keep leaking out. "Who owns it" has been tough to deal with, although "owned pointers" at least try. "Who locks it" has yet to be addressed at the language level, although at least there's now som…

I'm not sure what you mean by "global analysis," but Rust's borrow checker doesn't do any analysis that I'd consider "global."

D's ownership/borrowing system does data flow analysis within functions, i.e. it's intra-function. Inter-function (global) is handled via the function signature.
Post reply on HN