Live data from Hacker News

Modern C++ Won't Save Us

alexgaynor.net

291–300 of 395 posts

Re: Modern C++ Won't Save Us

#291

Earlier quoted context omitted.

I agree with him. in many practical applications with well design class hierarchies it just really isn't much of an issue. Hasn't been for me either.

> with well design class hierarchies :eyes:

you can roll eyes at me all you want, but I've been programming in C++ for a long time. These memory access issues just don't seem to be a big problem for us in practice. That's because we wrap all raw memory manipulation in appropriate classes for our application, so it's just not an issue. I agree it could be an issue in theory.

Re: Modern C++ Won't Save Us

#292
post #283

Earlier quoted context omitted.

> Structure the code in a way such that it is obvious what happens. Use "semantic compression" (e.g. be clear about your concepts and factor them in free standing functions), but don't overabstract/overengineer. This sounds little different from "write good code, don't write bad code." I'm sure we all agree on these things, but I'm sure the people who write terrible code weren't trying to be unclear or trying to over…

>> Eliminate special cases. [...] > True enough, but that's so much easier in a language with sum types. These languages make it easier to have more special cases. There's a difference. > That's a pretty controversial viewpoint, since it makes composition impossible (indeed taken to its logical extreme this would mean never writing a library, whereas the grandparent was convinced that more use of libraries was the wa…

> I don't see why that should be the case.

At the most basic level, if project A makes use of library B and library C, then you want to be able to verify the behaviour of library B and library C independently and then make use of your conclusions when analysing project A. But if library B and library C use global state then you can't have any confidence that that will work. E.g. if both library B and library C use some other library D that has some global construct, then they will likely interfere with each other.

> Another possibility would be to have subproject-wide global state, and passing a pointer only to library API calls. The latter is also the most realistic case since most libraries take pointer handles.

At that point you're not using global state in the library, which was the point.

> you can always opt for process- or thread-wide global state

That doesn't solve the problem at all.

> Also called "singleton" in OOP circles. Singletons are nothing but global data with nondeterminstic initialization order and superfluous syntax crap on top.

Indeed, and they're seen as bad practice for the same reason as global state in general.

Re: Modern C++ Won't Save Us

#293
post #289
post #221

Earlier quoted context omitted.

A look into the type_traits header reveals that is_standard_layout is implemented with standard C++.

This is absolutely false. https://github.com/llvm-mirror/libcxx/blob/master/include/ty...

It checks if a non standard feature is available, otherwise falls back to a standard implementation.

My argument was that it was possible to implement it with standard C++.

Re: Modern C++ Won't Save Us

#294
post #292

Earlier quoted context omitted.

>> Eliminate special cases. [...] > True enough, but that's so much easier in a language with sum types. These languages make it easier to have more special cases. There's a difference. > That's a pretty controversial viewpoint, since it makes composition impossible (indeed taken to its logical extreme this would mean never writing a library, whereas the grandparent was convinced that more use of libraries was the wa…

> I don't see why that should be the case. At the most basic level, if project A makes use of library B and library C, then you want to be able to verify the behaviour of library B and library C independently and then make use of your conclusions when analysing project A. But if library B and library C use global state then you can't have any confidence that that will work. E.g. if both library B and library C use so…

> At that point you're not using global state in the library, which was the point.

Yes. But I want to make clear that you are still using global state for all uses within the project itself. The library can be implemented in whatever way. For example, setting the pointer in a global variable on API entry ;-)

> That doesn't solve the problem at all.

WHICH problem? I don't think there is one.

> Indeed, and they're seen as bad practice for the same reason as global state in general.

This is foolish. There is no problem with global state. Global state is a fact of life. Your process has one address space. It has (probably) one server socket for listening to incoming request. It has (probably) one graphics window to show its state. Whenever you have more (e.g. file descriptors, memory mappings, ...), well then you have a set of that thing, but you have ONE set :-). And so on.

You are not writing a thousand pseudo-isolated programs. But ONE. One entity composed of a fixed number of parts (i.e. modules, code files) that work together to do what must be done.

Why add indirection? Why make it hard to iterate over all open file descriptors? Why thread a window handle through 15 layers of function calls when you have only one graphics window? It adds a lot of boilerplate. It even brings some people to invent hard to digest concepts like monads or objects just to make that terrible code manageable. It makes the code unclear. Someone once described it with this analogy, "I don't say ''I'm meeting one of my wives tonight'', unless I have more than one".

Re: Modern C++ Won't Save Us

#295
post #15

Question - How does one write microcontroller code (or other memory-mapped I/O code) using a memory-safe language?

You can't, at least safely.

If you can write arbitrarily to any position in RAM then it's not a memory-safe language. You can hide accesses behind some kind of abstraction (unsafe blocks, libraries or whatever). But that's not a memory-safe language, it's the developer making a contract with himself agreeing to not allowing direct, straight accesses (like those caveats we C/C++ developers do to not make "memory bugs"). Some microcontrollers can protect certain memory areas and raise access faults, but those are the same faults for a program written in C, C++, assembler, etc., and not related to the language.

One make the safest RTOS in trendy-safe-lang for some small microcontroller, but the end-user (developers) would still be able to write some unsafe code and blow a fuse.

A different thing is for MCUs with MMU and/or an OS that handles virtual memory per process/thread, but that wasn't your question.

Re: Modern C++ Won't Save Us

#296

Earlier quoted context omitted.

> think if you need a very safe code, you shouldn't use the string_view or span without thinking about the potential consequences. That’s the whole point: your caveat shows that’s it’s C/C++ which are unsafe in their very nature and therefore should not be used in code exposed to potentially malicious (e.g. user or network) input. Which is just about everything useful. HPC are generally closed systems and have differ…

"which is just about everything useful". This statement is wildly without merit. Sure, for the typical user facing application HN readers talk about then C++ can certainly contain vulnerabilities that are worrisome. Many performance critical applications can tolerate vulnerabilities in favor of latency. It seems to me that the world of realtime systems including avionics, autonomous control software, trading, machine…

> The extreme low level control that C++ offers and powerful metaprogramming allows for performance that even Rust cannot hope to rival.

Rust is developed by mozilla because they needed a language they could write a faster browser in. The first rust component in mozilla was a CSS library they had attempted to parallalise twice in C++ (with some of the best C++ programmers) and failed. Rust treats 'can't be as fast as C' as a bug.

Re: Modern C++ Won't Save Us

#297

Earlier quoted context omitted.

What parts specifically? By my estimation, the only non-deprecated part of the standard library that really reeks of pre-C++11 (what I believe most consider the advent of "modern") is iostream. Most of e.g. the containers have been kept up to date with new features of the language (e.g. move semantics, constexpr). The standard library certainly is lacking things which are commonly used (say, JSON parsing or database…

> include only elements that have a somewhat settled, "obvious", lowest-common-denominator semantics Can you, from the top of your head, tell me what irregular modified cylindrical Bessel functions are and the last time you needed to use one? And yet, they were included in the standard library in C++17: https://en.cppreference.com/w/cpp/numeric/special_math/cyl_b...

I can't, but I bet they have a standard and well-accepted definition in the mathematical community.

In fact, pretty much any real-valued mathematical function passes the test.

The interface is settled, almost by definition since C++ functions are inspired by mathematical functions: pass in arguments, return result. Use range/domain exceptions or NaN for reporting such errors.

The semantics are obvious: compute the named function.

The interface is lowest-common-denominator: include float, double, and long double overloads.

In fact, the same or similar interface is used in almost every language I've encountered. To contrast, the same is absolutely not true of e.g. a database module. I don't think I've ever seen two alike, disagreeing over even basic things such as whether the cursor or the transaction is the basic unit of interaction.

Re: Modern C++ Won't Save Us

#298

Earlier quoted context omitted.

What parts specifically? By my estimation, the only non-deprecated part of the standard library that really reeks of pre-C++11 (what I believe most consider the advent of "modern") is iostream. Most of e.g. the containers have been kept up to date with new features of the language (e.g. move semantics, constexpr). The standard library certainly is lacking things which are commonly used (say, JSON parsing or database…

> The standard library certainly is lacking things which are commonly used (say, JSON parsing or database connection), I strongly disagree. It's quite obvious that the C++ standard library does not need to add support for "common things", because they already exist as third-party modules. In fact, this obsession to add all sorts of cruft to the C++ standard is the reason we're having this discussion. If there is no w…

> I strongly disagree

No you don't. Read the rest of the sentence you quoted :)

Re: Modern C++ Won't Save Us

#299
post #139

Earlier quoted context omitted.

It's a bona fide C++ killer for applications that are both security and performance critical. It's already gaining traction for those applications even within relatively conservative engineering organisations. That said, there are many performance-critical applications who are not security-critical, and in those I'd expect C/C++ to persist pretty much indefinitely. And many security-critical applications which are no…

It is a legitimate C killer. C++, not so much.

people who liked C (and didn't like C++) are more likely to move to go. Rust has a healthy community of ex and current C++ programmers.

Re: Modern C++ Won't Save Us

#300
post #292

Earlier quoted context omitted.

> I don't see why that should be the case. At the most basic level, if project A makes use of library B and library C, then you want to be able to verify the behaviour of library B and library C independently and then make use of your conclusions when analysing project A. But if library B and library C use global state then you can't have any confidence that that will work. E.g. if both library B and library C use so…

> At that point you're not using global state in the library, which was the point. Yes. But I want to make clear that you are still using global state for all uses within the project itself. The library can be implemented in whatever way. For example, setting the pointer in a global variable on API entry ;-) > That doesn't solve the problem at all. WHICH problem? I don't think there is one. > Indeed, and they're seen…

> Yes. But I want to make clear that you are still using global state for all uses within the project itself.

But if we believe in using libraries then often our project will itself be a library.

> The library can be implemented in whatever way. For example, setting the pointer in a global variable on API entry ;-)

And then you have the problem I mentioned: if there is a diamond dependency on your library then the thing using it will break.

> WHICH problem? I don't think there is one.

The problem of not being able to break down your project and understand it piecemeal.

> Global state is a fact of life. Your process has one address space. It has (probably) one server socket for listening to incoming request. It has (probably) one graphics window to show its state.

All those global things are a common source of bugs, as different pieces of the program make subtly different assumptions about them. Perhaps a certain amount of global state is unavoidable. That's not an argument against minimizing it.

> You are not writing a thousand pseudo-isolated programs. But ONE. One entity composed of a fixed number of parts (i.e. modules, code files) that work together to do what must be done.

If you write a program that can only be understood in its entirety, you'll be unable to maintain it once it becomes too big to fit in your head. Writing a thousand isolated functions gives you something much easier to understand and scale.

Post reply on HN