Carbon Copy No.11: Generics Part III Parameterized Types #6837
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.
-
Carbon Copy, March 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 roughly) every other month.
Toolchain update
We've shown in earlier toolchain updates that you can import C++ easily. Today, we'll look at using the C++ standard library.
Carbon uses Clang to give complex initializers the same semantics as in C++, including overload resolution, default arguments, constructor templates, and conversion functions. Existing complex C++ APIs have delicate and nuanced overload sets, so it's important to model initialization and overload resolution the same way as C++ in order to avoid surprising behavior.
Another example:
Here we are calling methods on
std::vectorsuch aspush_back. These methods are selected by C++ overload resolution, and instantiated from templates. We're also showing that you can do overloaded array access, and use streaming operators oncout.There are extra casts because, unlike C++, Carbon doesn't allow us to discard the
i32sign bit, even though we use C++ rules to select the overload. Without the conversion, we'd select a C++operator[](size_t)overload, and then reject the attempt to call it because there's no implicit conversion fromi32tou64in Carbon.Spotlight: Generics Part III
Let's say we were building a smart lamp that locally keeps track of how many elk are attending a cocktail party so it knows when it can turn on and off the lights. Assuming it's a narrow party room so guests must leave in the opposite order they arrived, we could use a stack.
In Carbon, you can use C++ functionality like the standard template library.
Example: https://godbolt.org/z/ev3cP75G1
Let's replicate the stack functionality in Carbon with the same flexibility between types, which is to say you could make a
Stackof nearly anything.An elk party isn't an elk party until everyone gets there
As we've discussed before, Carbon has two generics systems, checked generics and template generics (familiar from C++). In this case, we'll again use checked generics, as the intention is that checked generics are favored for API definitions.
Let's take a look at some code. (There's a running example on Compiler Explorer for reference.)
:!syntax indicates thatTandNare compile-time bindings.We're adding a requirement that any
Tmust support theCore.Copyinterface. This means just any random type won't work, but most built-in types do, likei32andchar. More on howCore.Copyis used below.The value of
Tis a type representing what kind of elements can be stored in the stack, andNis a compile-time parameter representing the maximum capacity of the stack.With checked generics, the definition of
Stackis fully type-checked by the compiler at the time it is defined, no matter what types ofTandNyou use.Sidebar: What is Core?
“Core” is the Carbon standard library. Part of it, known as "the prelude", is implicitly imported into every Carbon source file. This means fundamental types and interfaces are immediately ready to use, and this includes
Core.Copy. Other parts need to be explicitly imported using theCorepackage name; in these examples, we need to import"io"fromCoreto getCore.Print.Making a stack
Let's take a look at some implementations, written inside the class definition above.
This code is pretty straightforward. You may notice a (relatively) recent design change here: We now support reference parameters, which are marked with the
refkeyword, and we use that (instead of the obsoleteaddr) to makeselfmutable . Among other things, this means members are consistently accessed using "self." (and never "self->").Let's add some critical functions that use
T:Pushoperates on our compile-time typeTand does some basic stack stuff with it.The lines “
self.contents[self.size] = x” and “return self.contents[self.size]” are whyTneeds to supportCore.Copy. We're making a copy ofxwhen storing or returning it. (You could make an array of pointers, but then you'd copy the pointer.)Let's use our stack.
Parameterized types allow you to avoid writing near-duplicate definitions for different types. We'll upgrade our party-tracker to track drinks, too, by making
Ta struct type (see Carbon Copy #5 for more on those).Final thoughts
You can see, then, that parameterized types can be quite useful. Container classes are just the start.
The above example of a stack of structs doesn't quite work yet, as struct types don't implement
Core.Copyyet. (You can follow along on the issue.) You could replace the struct with a containing class called something likeDrinkingElk, and then that class would have to implementCopy.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:
charredesign #6710Recently closed leads issues including:
Wrap-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!
Carbon has the need for speed,
Wolff, Josh, Richard, and the Carbon team
Beta Was this translation helpful? Give feedback.
All reactions