mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 13:50:10 +01:00
Assisted-by: Claude and Antigravity with Gemini --------- Co-authored-by: Geoff Romer <gromer@google.com> Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
112 lines
4.4 KiB
Markdown
112 lines
4.4 KiB
Markdown
# Templates
|
|
|
|
<!--
|
|
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
Exceptions. See /LICENSE for license information.
|
|
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
-->
|
|
|
|
<!-- toc -->
|
|
|
|
## Table of contents
|
|
|
|
- [TODO](#todo)
|
|
- [Overview](#overview)
|
|
- [Types with template parameters](#types-with-template-parameters)
|
|
- [Functions with template parameters](#functions-with-template-parameters)
|
|
- [Overloading](#overloading)
|
|
- [Constraining templates with interfaces](#constraining-templates-with-interfaces)
|
|
|
|
<!-- tocstop -->
|
|
|
|
## TODO
|
|
|
|
This is a skeletal design, added to support [the overview](README.md). It should
|
|
not be treated as accepted by the core team; rather, it is a placeholder until
|
|
we have more time to examine this detail. Please feel welcome to rewrite and
|
|
update as appropriate.
|
|
|
|
## Overview
|
|
|
|
Carbon templates follow the same fundamental paradigm as C++ templates: they are
|
|
instantiated, resulting in late type checking, duck typing, and lazy binding.
|
|
They both enable interoperability between Carbon and C++ and address some
|
|
(hopefully limited) use cases where the type checking rigor imposed by generics
|
|
isn't helpful.
|
|
|
|
### Types with template parameters
|
|
|
|
When parameterizing a user-defined type, the parameters can be marked as
|
|
template parameters. The resulting type-function will instantiate the
|
|
parameterized definition with the provided arguments to produce a complete type
|
|
when used. Note that only the parameters marked as having this template behavior
|
|
are subject to full instantiation -- other parameters will be type checked and
|
|
bound early to the extent possible. For example:
|
|
|
|
```
|
|
class Stack(template T: type) {
|
|
var storage: buf(T);
|
|
|
|
fn Push(ref self, value: T);
|
|
fn Pop(ref self) -> T;
|
|
}
|
|
```
|
|
|
|
This both defines a parameterized type (`Stack`) and uses one (`buf`). Within
|
|
the definition of the type, the template type parameter `T` can be used in all
|
|
of the places a normal type would be used, and it will only by type checked on
|
|
instantiation.
|
|
|
|
### Functions with template parameters
|
|
|
|
Both deduced and explicit function parameters in Carbon can be marked as
|
|
template parameters. When called, the arguments to these parameters trigger
|
|
instantiation of the function definition, fully type checking and resolving that
|
|
definition after substituting in the provided (or computed if deduced)
|
|
arguments. The runtime call then passes the remaining arguments to the resulting
|
|
complete definition.
|
|
|
|
```
|
|
fn Convert[template T: type](source: T, template U: type) -> U {
|
|
var converted: U = source;
|
|
return converted;
|
|
}
|
|
|
|
fn Foo(i: i32) -> f32 {
|
|
// Instantiates with the `T` deduced argument set to `i32` and the `U`
|
|
// explicit argument set to `f32`, then calls with the runtime value `i`.
|
|
return Convert(i, f32);
|
|
}
|
|
```
|
|
|
|
Here we deduce one type parameter and explicitly pass another. It is not
|
|
possible to explicitly pass a deduced type parameter, instead the call site
|
|
should cast or convert the argument to control the deduction. The explicit type
|
|
is passed after a runtime parameter. While this makes that type unavailable to
|
|
the declaration of _that_ runtime parameter, it still is a template parameter
|
|
and available to use as a type even within the remaining parts of the function
|
|
declaration.
|
|
|
|
### Overloading
|
|
|
|
An important feature of templates in C++ is the ability to customize how they
|
|
end up specialized for specific types. Because template parameters (whether as
|
|
type parameters or function parameters) are pattern matched, we expect to
|
|
leverage pattern matching techniques to provide "better match" definitions that
|
|
are selected analogously to specializations in C++ templates. When expressed
|
|
through pattern matching, this may enable things beyond just template parameter
|
|
specialization, but that is an area that we want to explore cautiously.
|
|
|
|
### Constraining templates with interfaces
|
|
|
|
Because we consider only specific _parameters_ to be templated and they could be
|
|
individually migrated to a constrained interface using the
|
|
[checked-generics system](README.md#generics), constraining templates themselves
|
|
may be less critical. Instead, we expect parameterized types and functions may
|
|
use a mixture of checked and template generic parameters based on where they are
|
|
constrained.
|
|
|
|
However, if there are still use cases, we would like to explore applying the
|
|
interface constraints of the checked-generics system directly to template
|
|
parameters rather than create a new constraint system.
|