What would I want in a C++ successor?
Projects like carbon and
cppfront promise upgrade paths from C++
to a better, safer systems language. What would I want to see from such a
language?
—
Safer and saner alternatives to C/C++
have been all the rage recently. While I
agree that languages like Rust
should be the future, steep learning curves and
thorny experience around FFI make it hard to recommend for codebases that are
already in C/C++
. I agree with the spirit of carbon
and cppfront
in
building a better upgrade path, and I thought it would be interesting to write
about what features I would want to see from such languages/ecosystems. This
post is mainly just a thought exercise, and I do think that carbon
/cppfront
tackle a lot of these issues in a really good way. I’m not sure that I’d
actively advocate for another language in this space, and I think resources are
better spent on new languages that significantly move the needle like Rust
and
Austral
instead.
Is C++
really that bad?
Hating on C++
is a bit of meme. While you’d be hard pressed to find developers
who see no flaws in it, I also think that a lot of complaints around C++
are
outdated or exaggerated. For example, using RAII
/smart pointers alleviates
many common sources of memory leaks, and concepts
allows duck typing for
template parameters - greatly simplifying how template errors are presented.
However, C++
still has many sharp edges. Implicit copying, hidden operator
overloading, confusing compiler errors, and optimizations allowed by the
spec that are often unexpected (e.g. std:vector<bool>
, signed integer
overflow) are all reasons that I think we need a successor language.
Sketching out my desired language
Syntax
I’d probably want something pretty close to existing C++
since it’s meant to
be easy to interop with legacy code. I’d probably want to change the lambda
function syntax, and make the capturing mode more explicit. Ideally, I’d maybe
even prefer something that looks more like normal function declaration.
Hygienic Macros
C++
macros are very cool, but leave a lot to be desired in terms of safety.
Rust
’s approach to macros is much better, and I could see that being
incorporated into C++
relatively easily.
No implicit copying
As the title says.
Safer multithreading
Rust
’s borrow checker helps expose issues in references shared by
multithreaded code. Something similar to that would be a welcome C++
addition.
There’s probably some opportunities for optimization here too - Rust
makes a
difference between Rc
and Arc
which means that single threaded usage of
shared pointers don’t need to pay an extra cost for atomic operations.
I’d also like to at least see ways to specify annotations on struct member/function parameters to require that some fields/values are only accessed with a lock.
No std::vector<bool>
gotchas
std::vector<bool>
is allowed to be implemented as a special case by being a
bitvector. In practice, this makes it easy to write multithreaded code with
subtle bugs - if two threads modify two indices that are close enough to be on
the same cache line then the two writes will race, which is hard to spot from a
code review alone. It would be safer for a new type bitvector
to be allowed to
have such optimization, with an understanding that std::vector<bool>
has more
emphasis on not being unexpected than being fast.
defined behavior for signed integer extension
Doesn’t matter what it’s defined to do, so long as it’s defined. Optimizations that rely on assuming that signed integer operations won’t overflow should be opt-in, or gated behind some other type.
Algebraic data types
They’re v cool
Linear Types
Linear types allow for many invalid programs to be rejected at compile time. I’ve approached this problem in a slightly different way before in my project rainbow which allows users to annotate functions with a tag (“color”), and then specify rules for callgraphs which should be rejected. If I was inventing a new language, linear types would solve the same problems more elegantly.
coroutines
C++20
has coroutines, but there’s a lot of sharp edges. Making them easier to
use would be nice.
better compiler error messages
C++
compiler errors are notoriously ugly. While most of time you can carefully
examine the error and figure out what went wrong, it’s safe to say that the
developer experience could be improved.
Conclusion
This was a pretty fun exercise! It’s a good way to reflect on all the weird
patterns and workarounds I’ve dealt with, and it’s made me both think about
ways in which the language can be improved, but also ways in the which the
language has already improved (e.g. with concepts, I think a lot of the times I’ve
reached for CRTP
can be rewritten more cleanly). Maybe it could be fun to
repeat this exercise for other languages like python in the future.