# Types
## Overview
A user-defined `type` is written using the same **name `:` kind `=` value** [declaration syntax](../cpp2/declarations.md) as everything in Cpp2. The type's "value" is a `{}`-enclosed body containing more declarations.
In a `type`, data members are private by default, and functions and nested types are public by default. To explicitly declare a type scope declaration `#!cpp public`, `#!cpp protected`, or `#!cpp private`, write that keyword at the beginning of the declaration.
``` cpp title="Writing a simple type" hl_lines="1"
mytype: type =
{
// data members are private by default
x: std::string;
// functions are public by default
protected f: (this) = { do_something_with(x); }
// ...
}
```
## `#!cpp this` The parameter name
**`#!cpp this`** is a synonym for the current object. Inside the scope of a type that has a member named `member`, `member` by default means `#!cpp this.member`.
> Note: In Cpp2, `#!cpp this` is not a pointer.
The name `#!cpp this` may only be used for the first parameter of a type-scope function (aka member function). It is never declared with an explicit `: its_type` because its type is always the current type.
`#!cpp this` can be an `in` (default), `inout`, `out`, or `move` parameter. Which you choose naturally determines what kind of member function is being declared:
- **`#!cpp in this`**: Writing `#!cpp myfunc: (this /*...*/)`, which is shorthand for `#!cpp myfunc: (in this /*...*/)`, defines a Cpp1 `#!cpp const`-qualified member function, because `in` parameters are `#!cpp const`.
- **`#!cpp inout this`**: Writing `#!cpp myfunc: (inout this /*...*/)` defines a Cpp1 non-`#!cpp const` member function.
- **`#!cpp out this`**: Writing `#!cpp myfunc: (out this /*...*/)` defines a Cpp1 constructor... and more. (See below.)
- **`#!cpp move this`**: Writing `#!cpp myfunc: (move this /*...*/)` defines a Cpp1 `#!cpp &&`-qualified member function, or if there are no additional parameters it defines the destructor.
For example, here is how to write read-only member function named `print` that takes a read-only string value and prints this object's data value and the string message:
``` cpp title="The this parameter" hl_lines="4 6"
mytype: type = {
data: i32; // some data member (private by default)
print: (this, msg: std::string) = {
std::cout Note: Generating `#!cpp inout this` (assignment) from `#!cpp out this` also generates **converting assignment** from converting construction, which is a new thing. Today in Cpp1, if you write a converting constructor from another type `X`, you may or may not write the corresponding assignment from `X`; in Cpp2 you will get that by default, and it sets the object to the same state as the converting constructor from `X` does.
### Minimal functions generated by default
There are only two defaults the language will generate implicitly for a type:
- The only special function every type must have is the destructor. If you don't write it by hand, a public nonvirtual destructor is generated by default.
- If no `#!cpp operator=` functions other than the destructor are written by hand, a public default constructor is generated by default.
All other `#!cpp operator=` functions are explicitly written, either by hand or by opting into applying a metafunction (see below).
> Note: Because generated functions are always opt-in, you can never get a generated function that's wrong for your type, and so Cpp2 doesnt need to support "=delete" for the purpose of suppressing unwanted generated functions.
### Memberwise by default
All copy/move/comparison `#!cpp operator=` functions are memberwise by default in Cpp2. That includes when you write memberwise construction and assignment yourself.
In a hand-written `#!cpp operator=`:
- The body must begin with a series of `member = value;` statements, one for each of the type's data members (including base classes) in declaration order.
- If the body does not mention a member in the appropriate place in the beginning section, by default the member's default initializer is used.
- In an assignment operator (`#!cpp inout this`), you can explicitly skip setting a member by writing `member = _;` where it would normally be set if you know you have a reason to set its value later instead or if the existing value needs to be preserved. (This is rare; for an example, see the generated implementation of the [`union` metafunction](metafunctions.md#union).)
For example:
``` cpp title="Memberwise operator= semantics" hl_lines="9-11 20-22"
mytype: type
= {
// data members (private by default)
name: std::string;
social_handle: std::string = "(unknown)";
// conversion from string
operator=: (out this, who: std::string) = {
name = who;
// if social_handle is not mentioned, defaults to:
// social_handle = "(unknown)";
// now that the members have been set,
// any other code can follow...
print();
}
// copy/move constructor/assignment
operator=: (out this, that) = {
// if neither data member is mentioned, defaults to:
// name = that.name;
// social_handle = that.social_handle;
print();
}
print: (this) = std::cout Note: This makes memberwise semantics symmetric for construction and assignment. In Cpp1, only non-copy/move constructors have a default, which is to initialize a member with its default initializer. In Cpp2, both constructors and assignment operators default to using the default initializer if it's a conversion function (non-`that`, aka non-copy/move), and using memberwise `member = that.member;` for copy/move functions.
## `#!cpp operator` Unified comparisons
To write comparison functions for your type, usually you just need to write either or both of `operator` and `operator==` with a first parameter of `this` and a second parameter of any type (usually `that` which is of the same type). If you omit the function body, a memberwise comparison will be generated by default.
`operator` must return one of `std::strong_ordering`, `std::partial_ordering`, or `std::weak_ordering`. It makes `=` comparisons available for your type. Prefer a strong ordering unless you have a reason to use a partial or weak ordering. If you write `operator` without a custom function body, `operator==` is generated for you.
`operator==` must return `bool`. It makes `==` and `!=` comparisons available for your type.
For example:
``` cpp title="Writing the operator" hl_lines="5-7 13"
item: type = {
x: i32 = ();
y: std::string = ();
operator: (this, that) -> std::strong_ordering;
// memberwise by default: first compares x that.x,
// then if those are equal compares y that.y
// ...
}
test: (x: item, y: item) = {
if x != y { // ok
// ...
}
}
```
The above is the same as in Cpp1 because most of Cpp2's `#!cpp operator` feature has already been merged into ISO C++ (Cpp1). In addition, in Cpp2 comparisons with the same precedence can be safely chained, and always have the mathematically sound transitive meaning or else are rejected at compile time:
- **Valid chains: All `=`, or all `==`.** All mathematically sound and safe chains like `a = b < c` and `a != b != c` are compile time errors. They are "nonsense" because they are non-transitive; these chains do not imply any relationship between `a` and `c`.
- **Non-chains: Mixed precedence is not a chain.** Expressions like `a