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.

Written on March 6, 2024