Which only do bounds checking in debug builds, or when explicitly use the compiler switches to enable them in release builds, good luck trying to advocate for using at() everywhere instead of braces.
Before C++ got the STL, all collections libraries shipped with compilers used to have bounds checking enabled by default, apparently that is too much performance loss for the standard library.
Walter's proposal added bounds checking being used unless explicitly disabled, like in any sane systems language.
As experience has shown, bounds checking is needed in the release builds, because those array overflows are only discovered by hackers in the released software.
D compilers allow that to be turned off, but it's only appropriate when:
1. evaluating how much the checking costs in runtime performance
Exactly, as any sane systems programming language. :)
I always force enable bounds checking on C++ code, never had a performance issue where the real culprit wasn't something else, wrong algorithm or data structure for the problem at hand.
Nobody has ever accused C++ of having good defaults. That is also unfortunately one of the hardest things possible to change without language-fragmentating mega breakages (see Python3)
I think the core issue here is that WG21 seems hell bent on refusing any new syntax if at all possible, and instead requires "generic" solutions that can be used for many problems. The result of which is these unending train wreck solutions for what should be basic, and we end up with enable_if and SFINAE. At least C++ finally has the idea of specifying an interface for a template instantiation, except of course it's absurd in its own way. Rather than specifying an API, you write "code" and a type conforms to that concept if the code "compiles". So you have no way to say "I expect this type to conform to this concept" other than using it.
The primary goal of "concepts" appears to be to mitigate the awful error messages, but even for that it fails.
For example, let's imagine Hashable from any other language, and look at a C++ concept version:
template <typename T>
concept Equatable = requires (const T& a, const T& b) {
{ a == b } -> std::same_as<bool>;
};
template <typename T>
concept Hashable = Equatable<T> && requires (const T& a) {
{ a.hashCode() }->std::convertible_to<size_t>;
};
Now how do we make sure Thing is actually going to conform to Hashable? with an assert of course, why would we want anything so gauche as declarative syntax?
static_assert(Hashable<Thing>);
You can see the brilliant syntax explicitly disallows us specifying constraints on a concept, and instead we have to use the && expression. My personal belief here is that the banning of constraints in the template name is simply to force people to use logical composition so the people who thought of it can claim people like it.
Hardly. A std library update is often easier and faster to ship than a new compiler toolchain. Especially in C/C++ world, although it is moderately uniquely terrible in this regard
> 5. one construct instead of two (vector and span)
Incorrect. Vector is an owned type, while both span and your proposal are borrowed types.
> 6. overflow behavior selectable with compiler switch
That sounds an awful lot like a negative to me, not a feature. It's not generally desirable for code behavior to change depending on how it's compiled, makes debugging kinda hard.
Unless you're just referring to things like sanitizers, in which case yeah span & vector both have those same flags.
> It's not generally desirable for code behavior to change depending on how it's compiled, makes debugging kinda hard.
It only changes the behavior of what happens after the program has already failed. People want different behaviors, depending on their environment, and like having the choice.
D's slices "T[]" maps to C++'s span<T> -- you're right, though the semantics/APIs of each are slightly different you can treat them as approximate concepts.
Before C++ got the STL, all collections libraries shipped with compilers used to have bounds checking enabled by default, apparently that is too much performance loss for the standard library.
Walter's proposal added bounds checking being used unless explicitly disabled, like in any sane systems language.