← Back to context

Comment by AlotOfReading

6 months ago

    The capabilities of a language are not defined by its worst programmers.

Is the implication here that Bjarne is a bad C++ developer? If the person in charge of the EWG fails "to use the language competently in all cases", what hope is there for the rest of us mere mortals?

For what it's worth, unsafe Rust is safer than C++. There's very little UB to explode your carefully crafted implementations. Safe rust of course has no UB except for what you write in unsafe blocks, so it's safer still and there's no real difference in the abstractions you can write with concepts vs traits.

I'm not actually arguing for rust here though, because this isn't a great showing for it. Trying to write the related add_wrap(T, T) function in rust is stupidly verbose compared to add_sat(T, T) thanks to bad decisions the num_traits authors made. What I am saying is C++ isn't a form of high level assembly like your original comment suggested. Understanding the relationship between the language and the hardware takes a lot of experience that most people don't use when writing code.

UB is a feature of the standard, not the implementation. Many of those behaviors can be defined. Modern C++ conveniently allows you to replace many of the bits that have UB, per standard, with your own bits with defined behavior with zero overhead. This was not always the case. You aren’t dependent on the compiler implementor. The ability to consistently do this transparently became practical around C++17 IMO. The C++ standard library is in many regards obsolete and many orgs treat it that way.

I never suggested that C++ was “a form of high level assembly”. I’ve written enough assembly and C to know better; you lose a bit of precision with C++. But now I can define (or not) the behavior I want in a way that is largely transparent. This has been a brilliant change to the language.

If you have a foundational library that makes different and/or explicit guarantees than std, it is pretty easy to police that in a code base with automation. Everyone doing high-performance and/or high-assurance systems is dragging in few if any dependencies, so this is practical. The kinds of things that C++ is really good at for new code are the kinds of things where this is what you would do regardless.

Developers don’t even have to be hardware experts, they just have to not use std for most things. That is a pretty low barrier. And std is a mess with the albatross of legacy support. Reimagined C++20 native “standard” libraries are much, much cleaner and safer (and faster).

Legacy C++ code bases aren’t going to be rewritten in a new language. New C++ code bases can take advantage of alternative foundations that ignore std and many do. Most things should not be written in C++, but for some things C++ is unmatched currently and safer in practice than is often suggested with basic hygiene.

  •     Modern C++ conveniently allows you to replace many of the bits that have UB, per standard, with your own bits with defined behavior with zero overhead.
    

    Okay, let's continue the example. Please demonstrate how to replace the addition operator on a primitive type. You can't within the confines of the language and that's a good thing in most cases. What you can do is pass -fwrapv, except that MSVC doesn't officially define a comparable flag.

        Developers don’t even have to be hardware experts, they just have to not use std for most things.
    

    Signed overflow isn't a problem with std, the solution to it is in std. Null pointers aren't a problem with std, but the recommended fixes are again in std. Etc.

        If you have a foundational library that makes different and/or explicit guarantees than std, it is pretty easy to police that in a code base with automation.
    

    As far as I'm aware, neither folly, absl, nor boost define custom integral types with defined overflow behavior. Please provide examples of anyone doing that.

        UB is a feature of the standard, not the implementation. 
    

    If you're writing "high assurance code", surely you're writing to the standard and not the implementation? The implementation's guarantees change with every upgrade, every new flag, and each time you build for different targets. I certainly try to avoid compiler assumptions as someone who writes safety critical code.