Repository navigation
Carbon Copy No.13: Operator overloading #7677
wolffg
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Carbon Copy, August 2026
Here is the new Carbon Copy, your periodic update on the Carbon language!
Carbon Copy is designed for those people who want a high-level view of what's happening on the project. If you'd like to subscribe, you can join announce@carbon-lang.dev. Carbon Copy should arrive roughly (sometimes extremely, extremely roughly) every other month.
Toolchain update
As of #7462 and #7595, Carbon can export generic classes and functions to C++.
C++ can call a Carbon function such as
fn F[T: type](t: T)orfn F[T: SomeInterface](t: T). In C++ code, these exported functions act like function templates.Example:
See it in Compiler Explorer!
And similarly, C++ can use parameterized classes from Carbon:
Also: Syntax changes to declarations
First, under Carbon Proposal #7016 updates the syntax for class (and interface/impl) methods to move
selfinto the parameter parentheses(...)and make the type in its binding optional (defaulting toSelf).Secondly, under Carbon Proposal #7254, the :! syntax was officially removed and replaced by a less-noisy system of contextual defaults and explicit phase keywords (
generic,template, andruntime). Above, we used the contextual defaults, but check out the proposal for the updates.This change does break some of the samples in previous spotlights. We'll be looking at updating those soon. Thanks for your patience!
Spotlight: Operator overloading
Ernesta the Knifefish is doing some designs with Carbon, and needs to create a complex number representation, commonly used in electrical engineering to represent both amplitude and wavelength in a single computation.1
When the operand types and the result type are all identical, the
+the operator would be overloaded by implementing the Add interface for that type, which would look like this:Core.Addis a named constraint, making it easier to define theCore.AddWithinterface when the parameters and the return type are all the same:Note:
Core.Addis not yet implemented and exposed. The aboveimplis equivalent to this code, which does work in the current toolchain:The expression
x + yis systematically rewritten by the compiler to an interface method call:x.(AddWith(U).Op)(y).See this in Compiler Explorer!
Contrasting overloading to C++
C++ operator overloading is ad-hoc. Coders must choose between writing member functions or declaring free functions in a namespace, relying on an open overload-resolution pass to match them. C++ templates are late-checked and structurally conformant (duck-typed); the compiler only checks if a type supports an operator when the template is instantiated. This results in slow compilations and hard-to-read error messages when a type lacks an operator.
Carbon adheres to the "one static open extension mechanism" principle, that all open extensions, including operator overloading, must go through nominal interface implementations (
impl ... as ...). Carbon generics are fully type-checked at the definition site. A generic function that needs to, say, add values constrains its type parameters with the nominal interface (e.g.,T impls Add). The compiler verifies that the generic code is valid immediately, without needing to instantiate the code first.C++ allows developers to define conflicting operators in different translation units or namespaces, which often results in silent and dangerous ODR (One Definition Rule) violations. Carbon enforces implementation coherence via strict orphan and overlap rules. In Carbon, a type can have exactly one implementation of an interface in the entire program. This ensures that learning more about a type (such as importing a library) never silently changes how an expression like
x + ybehaves.Mixed types and overloading
The above example only has two identical types being added. Ernesta needs some energy to do her engineering work, so let's do some heterogeneous addition by mixing up some java2.
First, let's set up some basic classes and the first homogeneous operator.
Mocha is coffee + chocolate, so we have a specialized
AddWith.Making a new
Mochaobject looks the same as makingCoffee, as they have the same fields, but the automatic conversion of the struct to the return type takes care of knowing we're returning Mocha.Using generics allows you to define functionality without being specific about implementation:
Because
UandTare declared inside deduced brackets[...], they default to checked generic parameters (symbolic constants) rather than templates. This means the compiler fully type-checks the body ofBlendat its definition site, verifying it is valid for any types that satisfy these constraints, without needing to instantiate the code first.Let's try it out.
Alas, Ernesta never implemented mixing two mochas together. The checked-generics part of this means if we write an unhandled case, we'll get a simple error at compile time.
The source pointer in the error points directly back to the definition of
BlendinCoffeeMachine.Have a cuppa joe in Compiler Explorer!
Conclusion
As we have often said about Carbon, there is one mechanism for generics to support a variety of features including operator overloading. Learn one thing, you know everything! Also, the intent is always to give short, specific errors no matter what the problem.
There are a lot of choices for the next spotlight. Write it in if you'd like to know more about how we handle C++ macros across the language boundaries, or else if you have another topic you're curious about!
Recent proposals and issues
If you want to keep up on Carbon’s proposals and issues, follow "Last Week In Carbon". Check out the RSS feed!
Recently accepted proposals including:
:!and:?with keywords and contextual defaults #7254selfsyntax and addingstaticmember variables #7016Recently closed leads issues including:
Destructor#7508:!syntax for generics and templates? #6932Wrap-up
Don't forget to subscribe! You can join announce@carbon-lang.dev. If you have comments or would like to contribute to future editions of Carbon Copy, please reach out. And, always, join us any way you can!
We went to Boron because we were after the 6th element in zero-based indexing,
Wolff, Josh, Richard, and the Carbon team
Footnotes
Ernesta, is, of course, an electric eel. 3 ↩
No, not Java, the liquid kind of java. ↩
Eels are knifefish. I just learned that. There are also electric catfish. Who knew? (I mean, outside of the catfish, who definitely knew after an awkward high-five.) ↩
All reactions