Timur Doumler (@timur_audio) on X

2 min read Original article ↗

user avatar

The Cpp2 compiler, called Cppfront, is not a full compiler, but actually translates Cpp2 code into Cpp1 (today's C++) which can in turn be consumed by any conforming C++ compiler. The C++ output is tuned to be human-readable. 1/13

user avatar

New syntax, for example auto main() -> int { ... } becomes main: () -> int = { ... } Cpp2 grammar is context-free, you never need to do sema in order to parse Cpp2 code. Lots of syntax cleanups but overall syntax doesn't look wildly different (unlike Carbon). 2/13

user avatar

The different grammar makes it easy for the compiler to distinguish Cpp2 code from Cpp1 code. The compiler can compile either pure Cpp2 code or you can have Cpp2/Cpp1 mixed mode in the same file. In pure Cpp2 mode, you can't have headers (use modules), there are no macros. 3/13

user avatar

Cpp2 gets the defaults right, for example any function is [[nodiscard]] by default. Pattern matching is built in (using his "is" and "as" syntax from wg21.link/p2392) 4/13

user avatar

Lambda syntax is a lot shorter and looks pretty much like regular functions but unnamed. No capture clause, instead you just capture in the body of the lambda, using a $ postfix. Lambdas always capture by value. There is also string interpolation (also using a $ character). 5/13

user avatar

A function can now return multiple return values like this: f: () -> (i: int, s: std::string) which gets translated to returning an instance of an unnamed struct with two members that can bind to a structured binding at the call site. 6/13

user avatar

Cpp2 is a safe language. Pointer arithmetic doesn't exist. You use span, which is bounds-checked. There are no owning raw pointers, no naked new/delete, therefore also no memory leaks/dangling pointers. 7/13

user avatar

Instead of naked new, you get shared.​new and unique.​new, which returns a shared_ptr and unique_ptr, respectively. There is a plain "new" which by default returns a unique_ptr. 8/13

user avatar

All types (including pointers, memory buffers, etc) follow the same initialisation rules. You don't need std::move and std::forward anymore. Move is automatic on definite last use. 12/13

user avatar