Skip to content

Commit

Permalink
metafunctions
Browse files Browse the repository at this point in the history
  • Loading branch information
gregmarr committed Feb 17, 2024
1 parent 8a14a56 commit 5662187
Showing 1 changed file with 7 additions and 4 deletions.
11 changes: 7 additions & 4 deletions docs/cpp2/metafunctions.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The most important thing about metafunctions is that they are not hardwired lang

## Applying metafunctions

Metafunctions provide an easy way for a type author to opt into a group of defaults, constraints, and generated functions: Just write `@name` afer the `:` of a declaration, where `name` is the name of the metafunctions. This lets the type author declare (and the human reader see) the intent up front: "This isn't just any `type`, this is a `@value type`" which automatically gives the type default/copy/move construction and assignment, `<=>` with `std::strong_ordering` comparisons, and guarantees that it has a public destructor and no protected or virtual functions:
Metafunctions provide an easy way for a type author to opt into a group of defaults, constraints, and generated functions: Just write `@name` afer the `:` of a declaration, where `name` is the name of the metafunction. This lets the type author declare (and the human reader see) the intent up front: "This isn't just any `type`, this is a `@value type`" which automatically gives the type default/copy/move construction and assignment, `<=>` with `std::strong_ordering` comparisons, and guarantees that it has a public destructor and no protected or virtual functions:

``` cpp title="Example: Using the value metafunction when writing a type"
point2d: @value type = {
Expand Down Expand Up @@ -95,7 +95,7 @@ skat_game: @enum<i16> type = {

Consider `hearts`: It's a member object declaration, but it doesn't have a type (or a default value) which is normally illegal, but here it's okay because the `@enum<i16>` metafunction fills them in: It iterates over all the data members and gives each one the underlying type (here explicitly specified as `i16`, otherwise it would be computed as the smallest signed type that's big enough), and an initializer (by default one higher than the previous enumerator).

Unlike C `enum`, this `@enum` is scoped and strongly typed (does not implicitly convert to the underlying type.
Unlike C `enum`, this `@enum` is scoped and strongly typed (does not implicitly convert to the underlying type.)

Unlike C++11 `enum class`, it's "just a `type`" which means it can naturally also have member functions and other things that a type can have:

Expand Down Expand Up @@ -141,7 +141,8 @@ file_attributes: @flag_enum<u8> type = {
// name_or_number is declaratively a safe union/variant type:
// it has a discriminant that enforces only one alternative
// can be active at a time, members always have a name, and
// each member has .is_member() and .member() accessors...
// each member has .is_member() .set_member() and .member()
// accessors using the member name...
// the word "union" carries all that meaning as a convenient
// and readable opt-in without hardwiring "union" specially
// into the language
Expand All @@ -155,7 +156,9 @@ main: () = {
x: name_or_number = ();

x.set_name("xyzzy"); // now x is a string
std::cout << x.name(); // prints the string
if x.is_name() {
std::cout << x.name(); // prints the string
}

// trying to use x.num() here would cause a Type safety
// contract violation, because x is currently a string
Expand Down

0 comments on commit 5662187

Please sign in to comment.