How is the C type system slowing you down? I thought the complaints around C productivity were around memory management and low-level APIs (both of which can be mitigated using libraries: you can “abstract away” these problems and stay in C).
Like Walter Bright, I would love to have some sort of “span” or “slice” primitive. I would love language level tagged unions rather than writing them out each time. Pattern matching isn’t exactly a type system feature, but relies on it to work, and would make those more useful. The lack of destructors means a lot of manual handling of errors. The lack of generics makes it difficult to write generic data structures without losing type safety. There’s no real const.
There are ways to do all of these things, but they’re more manual, more error prone, and get in the way of doing the actual work you’re trying to do.
That describes the basic feature set of C++ very well.
People complain about C++ that it can do much more. Yea. But there is no need to use template meta-programming, multiple inheritance and other special features. Actually I think programmers shouldn’t use them in productive code.
Recently some projects switched the compiler to ‘g++’ and use the basic subset of C++. Makes sense? Maybe Herb Sutters “C++2” will evolve, main features are safety and simplicity.
I’m fine with both C and C++. They do a good job. Address-Sanitizer is a game changer! But I want more.
C++ 20 std::span is an example of how little WG21 actually cares about safety, correctness or other principles of software engineering.
The slice type you actually want has nice safety properties. The slice type proposed to WG21 about five years ago as std::span compromises a little bit, knowing they'd object to good engineering here, and it offers an unsafe way to access the slice as well as safe access. The committee voted to strip out safe access and specifically rejected efforts to ensure there was a sane way to use this type.
I assume Jarrad Waterloo's proposal to fix std::span in C++ 26 will get traction because it's now embarrassing for the project but there's no reason we should pretend this was some mere oversight. C++ is less safe than it should be on purpose.
I get similarly frustrated at the implementation of operator-> and operator* in std::optional. In what world would I want to provide accessors with no more safety than a raw pointer?
Edit: I was looking it up just to make sure I remembered it correctly, and there’s been a recent change that makes it worse. The operator-> and operator* on std::optional are now marked noexcept, so implementations are forbidden from making the accessors safe.
That's what I've heard, but since I'm not that in the weeds with that whole process, I didn't want to comment on it at that level.
It's struck me as being similar to operator* on Optional. I get why they did it. It makes sense. It's also unfortunate. I'm glad I'm not on that committee.
The need to express polymorphism manually in C, the need to remember to check errors returned by functions (instead of the monadic style of computation), the need to define closure's environment structures (those that are passed via something like `void *arg`), etc.
All these things are pretty tedious. And all these things are what other languages are doing under the hood. The difference is that C gives you a choice of _how_ to do (more) things; other languages do not.
Or, don't do polymorphism in C. It's not a mandatory technique. I love C, but I'd argue that if you're doing advanced OOP, you should use a more appropriate language.
Sum types. In C they can be constructed out of unions and structs with lots of checks (and possibility for error) but it's painful.
There's really no excuse for C not having them, other than C being designed before algebraic types became mainstream. They make certain programming errors impossible, particularly with null values and misusing a union with the wrong type. It is possible to compile them as a zero-cost abstraction, and essentially all recent languages aimed at the same domain as C (Rust, D, Go, Zig, Hare, etc.) include them.
Inability to specify non-nullable pointers, or truly immutable data, or ownership, or thread-safety of objects on the type system level means I have to remember these unwritten invariants in every case, and/or code defensively.
Libraries can't specify these things in a compiler-enforced way either, so they remain "RTFM" problems for programmers to deal with manually.
I mean, the type system it isn't checking still isn't as strong or powerful as I'd like, but it is there. Unlike your CPU which doesn't care, C agrees that in principle an integer, a pointer and a floating point value are in fact different kinds of thing.
I think Option<!> is excellent, C thinks I should just write a comment in the program instead, these are big differences but they aren't so fundamental as the difference between US corporate welfare and socialism.
> C agrees that in principle an integer, a pointer and a floating point value are in fact different kinds of thing.
Sure, but that's kiddie-pool, 1970s-level stuff compared to modern type systems.
No business in their right minds is saying, in 2023, let's develop a new system in C. If they are, it's because they have people stuck decades in the past who are arguing for it.
(Edit: or, of course, they need to integrate with a C system, the number of which "is too damn high".