{"id":21067065,"url":"https://github.com/ntrel/cpp2","last_synced_at":"2025-05-16T03:32:11.979Z","repository":{"id":146129259,"uuid":"538557967","full_name":"ntrel/cpp2","owner":"ntrel","description":"Overview of Herb Sutter's Cpp2 \u0026 cppfront","archived":false,"fork":false,"pushed_at":"2023-10-18T15:38:26.000Z","size":57,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2023-10-19T03:29:42.736Z","etag":null,"topics":["cppfront"],"latest_commit_sha":null,"homepage":"","language":"CSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ntrel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-09-19T15:02:15.000Z","updated_at":"2023-10-20T14:38:51.559Z","dependencies_parsed_at":null,"dependency_job_id":"74d2a8d4-79be-4823-9541-da30f74e672d","html_url":"https://github.com/ntrel/cpp2","commit_stats":null,"previous_names":[],"tags_count":0,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ntrel%2Fcpp2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ntrel%2Fcpp2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ntrel%2Fcpp2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ntrel%2Fcpp2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ntrel","download_url":"https://codeload.github.com/ntrel/cpp2/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225402638,"owners_count":17468836,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cppfront"],"created_at":"2024-11-19T18:02:51.912Z","updated_at":"2024-11-19T18:03:26.293Z","avatar_url":"https://github.com/ntrel.png","language":"CSS","readme":"# Cpp2 Language Overview\n\nDisclaimer:\n* These docs are unofficial and may be inaccurate or incomplete.\n  + Please file bugs at https://github.com/ntrel/cpp2/issues.\n* At the time of writing, Cpp2 is an *unstable experimental language*, see:\n  + https://github.com/hsutter/cppfront#cppfront\n  + https://github.com/hsutter/cppfront#wheres-the-documentation.\n\nNote: Some examples are snipped/adapted from:\nhttps://github.com/hsutter/cppfront/tree/main/regression-tests\n\nNote: Examples here use C++23 `std::println` instead of `std::cout`.\nIf you don't have it, you can use this definition:\n\n```c++\nstd: namespace = {\n    println: (args...) = (std::cout \u003c\u003c ... \u003c\u003c args) \u003c\u003c \"\\n\";\n}\n```\n\n# Contents\n\n* [Declarations](#declarations)\n* [Variables](#variables)\n* [Modules](#modules)\n* [Types](#types)\n* [Memory Safety](#memory-safety)\n* [Expressions](#expressions)\n* [Statements](#statements)\n* [Functions](#functions)\n* [User-Defined Types](#user-defined-types)\n* [Templates](#templates)\n* [Aliases](#aliases)\n\n\n# Declarations\n\nThese are of the form:\n\n * *declaration*:\n   + *identifier* `:` *type*? `=` *initializer*\n\n*type* can be omitted for type inference (though not at global scope).\n\n```c++\n    x: int = 42;\n    y := x;\n```\nA global declaration can be used before the line declaring it.\n\n## Mixing Cpp1 Declarations\n\nCpp1 declarations can be mixed in the same file.\n\n```c++\n// Cpp2\nx: int = 42;\n\n// Cpp1\nint main() {\n    return x; // use a Cpp2 definition\n}\n```\nA Cpp2 declaration cannot use Cpp1 declaration format internally:\n\n```c++\n// declare a function\nf: () = {\n    int x; // error\n}\n```\n\nNote: `cppfront` has a `-p` switch to only allow pure Cpp2.\n\n\n# Variables\n\n## Uninitialized Variables\n\nUse of an uninitialized variable is statically detected.\n\nWhen the variable declaration specifies the type, initialization can be\ndeferred to a later statement.\nBoth branches of an `if` statement must\ninitialize a variable, or neither.\n```c++\n    x: int;\n    y := x; // error, x is uninitialized\n    if f() {\n        x = 1; // initialization, not assignment\n    } else {\n        x = 0; // initialization required here too, otherwise an error\n    }\n    x = 2; // assignment\n```\n\n## Runtime Constants\n\n```c++\n    x: const int;\n    x = 5; // initialization\n    x = 6; // error\n```\n```c++\n    y: int = 7;\n    z: const _ = y; // z is a `const int`\n```\nNote that `x` does not need to be initialized immediately, it can deferred.\nThis is particularly useful when using `if` branches to initialize the\nconstant.\n\n\u003chttps://github.com/ntrel/cppfront/wiki/Design-note:-const-objects-by-default\u003e\n\n## Implicit Move on Last Use\n\nA variable is implicitly moved on its last use when the use site syntax\nmay accept an rvalue. This includes passing an argument to a function,\nbut not an assignment to the last use of a variable.\n```c++\ninc: (inout v: int) = v++;\n\ntest2: () = {\n    v := 42;\n    inc(v);     // OK, lvalue\n    inc(v);     // error, cannot pass rvalue\n}\n```\nThis can be suppressed by adding a statement `_ = v;` after the final `inc` call.\n\n\n# Modules\n\nCpp2 files have the file extensions `.cpp2` and `.h2`.\n\n## Imports\n\nC++23 will support:\n\n```c++\nimport std;\n```\nThis will be implicitly done in Cpp2. For now common `std` headers are imported.\n\n\n# Types\n\nSee also: [User-Defined Types](#user-defined-types).\n\n## Arrays\n\nUse:\n* `std::array` for fixed-size arrays.\n* `std::vector` for dynamic arrays.\n* `std::span` to reference consecutive elements from either.\n\n\n## Pointers\n\nA pointer to `T` has type `*T`. Pointer arithmetic is illegal.\n\n### Postfix Pointer Operators\n\nAddress of and dereference operators [are postfix](#postfix-operators):\n```c++\n    x: int = 42;\n    p: *int = x\u0026;\n    y := p*;\n```\nThis makes `p-\u003e` obsolete - use `p*.` instead.\n\nTo distinguish these from binary `\u0026` and `*`, use preceeding whitespace.\n\n\n### `new\u003cT\u003e`\n\n`new\u003cT\u003e` gives `unique_ptr` by default:\n\n```c++\n    p: std::unique_ptr\u003cint\u003e = new\u003cint\u003e;\n    q: std::shared_ptr\u003cint\u003e = shared.new\u003cint\u003e;\n```\nNote: `gc.new\u003cT\u003e` will allocate from a garbage collected arena.\n\nThere is no `delete` operator. Raw pointers cannot own memory.\n\n### Null Dereferences\n\nInitialization or assignment from null is an error:\n\n```c++\n    q: *int = nullptr; // error\n```\nInstead of using null for `*T`, use `std::optional\u003c*T\u003e`.\n\nBy default, `cppfront` also detects a runtime null dereference.\nFor example when dereferencing a pointer created in Cpp1 code.\n\n```c++\nint *ptr;\n\nf: () -\u003e int = ptr*;\n```\nCalling `f` above produces:\n\n    Null safety violation: dynamic null dereference attempt detected\n\n# Memory Safety\n\nCpp2 will not enforce a memory-safety subset 100%. It will diagnose\nor prevent type, bounds, initialization, and common lifetime memory-safety\nviolations. This is done by:\n\n* Runtime bounds checks\n* Requiring each [variable is initialized](#variables) before use in\n  every possible branch\n* *Not implemented yet:* Compile-time tracking of a set of 'points-to'\n  information for each pointer. When a pointed-to variable goes out of scope,\n  the set is updated to replace the variable with an invalid item.\n  Dereferencing a pointer with a set containing an invalid item is a\n  compile-time error.\n  See https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1179r1.pdf.\n\nSee:\n* https://github.com/hsutter/cppfront#2015-lifetime-safety\n* https://www.reddit.com/r/cpp/comments/16ummo8/cppfront_autumn_update/k2r3fto/\n\n## Bounds Checks\n\nBy default, `cppfront` does runtime bound checks when indexing:\n```c++\n    v: std::vector = (1, 2);\n    i := v[-1]; // aborts program\n\n    s: std::string = (\"hi\");\n    i = s[2]; // aborts program\n```\n\n# Expressions\n\n## Postfix Operators\n\nBesides the [pointer operators](#postfix-pointer-operators),\nCpp2 also only uses postfix instead of prefix form for:\n* `++`\n* `--`\n* `~`\n\nUnlike Cpp1, the immediate result of postfix increment/decrement is the new value.\n\n```c++\n    i := 0;\n    assert(i++ == 1);\n```\n\u003chttps://github.com/hsutter/cppfront/wiki/Design-note:-Postfix-operators\u003e\n\n\n## String Interpolation\n\nA bracketed expression with a trailing `$` inside a string will\nevaluate the expression, convert it to string and insert it into the\nstring.\n\n```c++\n    a := 2;\n    b: std::optional\u003cint\u003e = 2;\n    s: std::string = \"a^2 + b = (a * a + b.value())$\\n\";\n    assert(s == \"a^2 + b = 6\\n\");\n```\n\nNote: `$` means 'capture' and is also used in [closures](#function-literals)\nand [postconditions](#contracts):\n\u003chttps://github.com/hsutter/cppfront/wiki/Design-note%3A-Capture\u003e\n\n## Anonymous Variables\n\n* *anonymousVariable*:\n  + `:` *type*? `=` *expression*\n\n```c++\nf: (i: int)   = { std::println(\"int\"); }\nf: (i: short) = { std::println(\"short\"); }\n\nmain: () = {\n    f(5);          // int\n    f(:short = 5); // short\n}\n```\nThe last statement is equivalent to `tmp: short = 5; f(tmp);`.\n\n\n## Identifier Expressions\n\n* *identifierExpression*:\n  + *identifier*\n  + *identifier* `\u003c` *expressions* `\u003e`\n  + *expression* `::` *identifierExpression*\n\n### Required Parentheses\n\nWhenever any kind of identifier expression is used where it could parse\nas a type, it must be enclosed in parentheses:\n\n* `id1` - type\n* `(id1)` - expression\n\nAn identifier expression does not need parentheses where a type would\nnot be valid. Other expressions never need parentheses as they could\nnot be parsed as a valid type, e.g. literals, unary expressions etc.\n\n\n## `as`\n\n* *asExpression*:\n  + *expression* `as` *type*\n\n`x as T` attempts:\n* type conversion (if the type of `x` implicitly converts to `T`)\n* customized conversion (using `operator as\u003cT\u003e`), useful for `std::optional`,\n  `std::variant` etc.\n* construction of `T(x)`\n* dynamic casting (equivalent to Cpp1 `dynamic_cast\u003cT\u003e(x)` when `x` is a base class of `T`)\n\nAn exception is thrown if the expression is well-formed but the conversion is invalid.\n\n```c++\n    c := 'A';\n    i: int = c as int;\n    assert(i == 65);\n\n    v := std::any(5);\n    i = v as int;\n\n    s := \"hi\" as std::string;\n    assert(s.length() == 2);\n```\n\n## `is`\n\n* *isExpression*:\n  + *type* `is` (*type* | *template*)\n  + *expression* `is` (*type* | *expression* | *template*)\n\n### Type Tests\n\n*Not implemented yet*.\n\nTest a type `T` matches another type - `T is Target` attempts:\n* `true` when `T` is the same type as `Target`.\n* `true` if `T` is a type that [inherits](#inheritance) from `Target`.\n\nTest a type against a template - `T is Template` attempts:\n* `true` if `T` is an instance of `Template`.\n* `Template\u003cT\u003e` if the result is convertible to `bool`.\n\n### Expression Tests\n\nNote: Testing an identifier expression [needs to use parentheses](#required-parentheses).\n\nTest type of an expression - `(x) is T` attempts:\n* `true` when the type of `x` is `T`\n* `x.operator is\u003cT\u003e()`\n  + `(x) is void` means `x` is empty\n\n```c++\n    assert(5 is int);\n    i := 5;\n    assert((i) is int);\n    assert(!((i) is long));\n\n    v := std::any();\n    assert((v) is void); // `v.operator is\u003cvoid\u003e()`\n    v = 5;\n    assert((v) is int); // `v.operator is\u003cint\u003e()`\n```\n\nTest expression has a particular value - `(x) is v` attempts:\n* `x.operator is(v)`\n* `x == v`\n* `x as V == v` where `V` is the type of `v`\n* `v(x)` if the result is `bool`\n\n```c++\n    i := 5;\n    assert((i) is 5);\n    v := std::any(i);\n    assert((v) is 5);\n```\n\nThe last lowering allows to test a value by calling a predicate function:\n```c++\npred: (x: int) -\u003e bool = x \u003c 20;\n\ntest_int: (i: int) = {\n    if (i) is (pred) {\n        std::println(\"(i)$ is less than 20\");\n    }\n}\n\nmain: () = {\n    test_int(5);\n    test_int(15);\n    test_int(25);\n}\n```\nNote that `pred` is not a type identifier so it [must be parenthesized](#required-parentheses).\n\nTest an expression against a template - `(x) is Template` attempts:\n* `true` if the type of `x` is an instance of `Template`.\n* `Template\u003c(x)\u003e` if the result is convertible to `bool`.\n\n## `inspect`\n\n* *inspectExpression*:\n  + `inspect` `constexpr`? *expression* `-\u003e` *type* `{` *alternative*+ `}`\n* *alternative*:\n  + *alt-name*? *pattern* `=` *statement*\n  + *alt-name*? *pattern* `{` *alternative*+ `}`\n* *alt-name*:\n  + *identifier* `:`\n* *pattern*:\n  + `is` (*type* | *expression* | *template*)\n  + `as` *type*\n  + `if` *expression*\n  + *pattern* `||` *pattern*\n  + *pattern* `\u0026\u0026` *pattern*\n\nOnly `is` alternatives without *alt-name* are implemented ATM.\n\n```c++\nv : std::any = 12;\n\nmain: () = {\n    s: std::string;\n    s = inspect v -\u003e std::string {\n        is 5 = \"five\";\n        is int = \"some other integer\";\n        is _ = \"not an integer\";\n    };\n    std::println(s);\n}\n```\nAn `inspect` expression must have an `is _` case.\n\n*Unimplemented:* an `inspect` statement has the same grammar except\nthere must be no `-\u003e` *type* after the *expression*.\n\n\u003chttps://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2392r2.pdf\u003e\n\n\n## Move Expressions\nA variable can be explictly moved. The move constructor of `z` will destroy `x`:\n\n```c++\n    x: std::string = \"hi\";\n    z := (move x);\n    assert(z == \"hi\");\n    assert(x == \"\");\n```\nSee also [Implicit Move on Last Use](#implicit-move-on-last-use).\n\n\n# Statements\n\nA condition expression does not require parentheses in Cpp2, though when\na statement immediately follows a condition, a *blockStatement* is required.\n\n## `if`\n\n* *ifStatement*:\n  + `if` `constexpr`? *expression* *blockStatement* *elseClause*?\n* *elseClause*:\n  + `else` *blockStatement*\n  + `else` *ifStatement*\n\n```c++\n    if c1 {\n        ...\n    } else if c2 {\n        ...\n    } else {\n        ...\n    }\n```\n\n## Assertions\n\n```c++\n    x := 1\n    assert(x == 1);\n```\n\n## Parameterized Statement\n\n* *parameterizedStatement*:\n  + [*parameterList*](#functions) *statement*\n\nA parameterized statement declares one or more variables that are\ndefined only for the scope of *statement*.\n\n```c++\n(tmp := some_complex_expression) func(tmp, tmp);\n// tmp no longer in scope\n```\n\nValid *[parameterStorage](#parameter-passing)* keywords are `in`, `copy`, `inout`.\n\n## `while`\n\n* *whileStatement*:\n  + `while` *expression* *nextClause*? *blockStatement*\n* *nextClause*:\n  + `next` *expression*\n\nIf `next` is present, its expression will be evaluated at the\nend of each loop iteration.\n\n```c++\n    // prints: 0 1 2\n    (copy i := 0) while i \u003c 3 next i++ {\n        std::println(i);\n    }\n```\nNote: The above is a *parameterizedStatement*.\n\n## `do`\n\n* *doWhileStatement*:\n  + `do` *blockStatement* *nextClause*? `while` *expression* `;`\n\n```c++\n    // prints: 0 1 2\n    i := 0;\n    do {\n        std::println(i);\n    } next i++ while i \u003c 3;\n```\n\n## `for`\n\n* *forStatement*:\n  + `for` *expression* *nextClause*? `do` `(` *parameter* `)` *statement*\n\nThe first *expression* must be a range.\n*[parameter](#functions)* is initialized from each element of the\nrange. The parameter type is inferred. \n*parameter* can have `inout` *[parameterStorage](#parameter-passing)*.\n\n```c++\n    vec: std::vector\u003cint\u003e = (1, 2, 3);\n\n    for vec do (inout e)\n        e++;\n\n    assert(vec[0] == 2);\n    for vec do (e)\n        std::println(e);\n```\n\u003chttps://github.com/hsutter/cppfront/blob/main/regression-tests/mixed-intro-for-with-counter-include-last.cpp2\u003e\n\n\n## Labelled `break` and `continue`\n\nThe target of these statements can be a labelled loop.\n\n```c++\n    outer: while true {\n        j := 0;\n        while j \u003c 3 next j++ {\n            if done() {\n                break outer;\n            }\n        }\n    }\n```\n\n# Functions\n\n## Function Types\n\n * *functionType*:\n   + *parameterList* *returnSpec*\n * *parameterList*:\n   + `(` *parameter*? `)`\n   + `(` *parameter* (`,` *parameter*)+ `)`\n * *parameter*:\n   + *[parameterStorage](#parameter-passing)*? *type*.\n   + *[parameterStorage](#parameter-passing)*? *identifier* `...`? `:` *type*.\n * *returnSpec*:\n   + `-\u003e` (`forward` | `move`)? *type*\n   + `-\u003e` *parameterList*\n\nE.g. `(int, float) -\u003e bool`.\n\n## Function Declarations\n\n * *functionDeclaration*:\n   + *identifier*? `:` *parameterList* *returnSpec*? `;`\n   + *identifier*? `:` *parameterList* *returnSpec*? [*contracts*](#contracts)? `=` *functionInitializer*\n   + *identifier*? `:` *parameterList* *expression* `;`\n\nFunction declarations extend the [declaration form](#declarations).\nEach parameter must have an identifier.\n\nIf *returnSpec* is missing with the first two forms, the function returns `void`.\nThe return type can be inferred from the initializer by using `-\u003e _`.\n\nSee also [Template Functions](#template-functions).\n\n\n## Function Bodies\n\n * *functionInitializer*:\n   + (*expression* `;` | *statement*)\n\nA function is initialized from a statement or an expression.\n\n```c++\nd: (i: int) = std::println(i);\ne: (i: int) = { std::println(i); } // same\n```\n\nIf the function has a *returnSpec*, the expression form implies a `return` statement.\n\n```c++\nf: (i: int) -\u003e int = return i;\ng: (i: int) -\u003e int = i; // same\n```\n\nLastly, `-\u003e _ =` together can be omitted:\n```c++\nh: (i: int) i; // same as f and g\n```\nThis form is useful for [lambda functions](#function-literals).\n\n\n## Named Return Values\n\nWhen a function returns a *parameterList*, each parameter must be named.\nA function with multiple named return parameters returns a struct with\na member for each parameter.\n\n```c++\nf: () -\u003e (i: int, s: std::string) = {\n    i = 10;\n    s = \"hi\";\n}\n\nmain: () = {\n    t := f();\n    assert(t.i == 5);\n    assert(t.s == \"hi\");\n}\n```\n\n* Unless a return parameter has a default value, it must be initialized in\n  the function body.\n* When only one return parameter is declared, the caller does not\n  use member syntax to access the result.\n\n```c++\nf: () -\u003e (ret: int = 42) = {}\n\nmain: () = {\n    assert(f() == 42);\n}\n```\n\n## `main`\n\n* *mainFunction*:\n  + `main` `:` `(` `args`? `)` (`-\u003e` `int`)? `=` *functionInitializer*\n\nIf `args` is declared, it is a `std::vector\u003cstd::string_view\u003e` containing\neach command-line argument to the program.\n\n\n## Uniform Call Syntax\n\nIf a method doesn't exist when using method call syntax, and there is a\nfunction whose first parameter can take the type of the 'object'\nexpression, then that function is called instead.\n\n```c++\nmain: () -\u003e int = {\n    // call C functions\n    myfile := fopen(\"xyzzy\", \"w\");\n    myfile.fprintf(\"Hello %d!\", 2); // fprintf(myfile, \"Hello %d!\", 2)\n    myfile.fclose(); // fclose(myfile)\n}\n```\n\n## Parameter Passing\n\n* `in` - default, read-only. \n  Will pass by reference when more efficient, otherwise pass by value.\n* `inout` - pass by mutable reference.\n* `out` - must be written to.\n  Can accept an uninitialized argument, otherwise destroys the argument.\n  The first assignment constructs the parameter.\n  Used for [constructors](#operator).\n* `move` - argument can be moved from. Used for [destructors](#operator).\n* `copy` - argument can be copied from.\n* `forward` - accepts lvalue or rvalue, pass by reference.\n\n```c++\ne: (i: int) = i++; // error, `i` is read-only\nf: (inout i: int) = i++; // mutate argument\n\ng: (out i: int) = {\n    v := i; // error, `i` used before initialization\n    // error, `i` was not initialized\n}\n```\nFunctions can return by reference:\n```c++\nfirst: (forward v: std::vector\u003cint\u003e) -\u003e forward int = v[0];\n\nmain: () -\u003e int = {\n    v : std::vector = (1,2,3);\n    first(v) = 4;\n}\n```\n\u003chttps://github.com/hsutter/cppfront/blob/main/regression-tests/mixed-parameter-passing.cpp2\u003e\n\n## Contracts\n\n```c++\nvec: std::vector\u003cint\u003e = ();\n\ninsert_at: (where: int, val: int)\n    pre(0 \u003c= where \u0026\u0026 where \u003c= vec.ssize())\n    post(vec.ssize() == vec.ssize()$ + 1) = {\n    vec.insert(vec.begin() + where, val);\n}\n```\nThe postcondition compares the vector size at the end of the function call with\nan expression that captures the vector size at the start of the function call.\n\n\u003chttps://github.com/hsutter/cppfront/blob/main/regression-tests/mixed-postexpression-with-capture.cpp2\u003e\n\nA single [named return](#named-return-values) is useful to refer to a\nresult in a postcondition:\n```c++\nf: () -\u003e (ret: int)\n    post(ret \u003e 0) = {\n    ret = 42;\n}\n```\n\n## Function Literals\n\nA function literal is declared like a named function, but omitting the leading identifier.\nVariables can be captured:\n\n```c++\n    s: std::string = \"Got: \";\n    f := :(x) = { std::println(s$, x); };\n    f(5);\n    f(\"str\");\n```\n* `s$` means capture `s` by value.\n* `s\u0026$*` can be used to dereference the captured address of `s`.\n\n\n## Template Functions\n\nA [template](#templates) function declaration can have template parameters:\n\n * *functionTemplate*:\n   + *identifier*? `:` *templateParameterList*? *parameterList* *returnSpec*? *requiresClause*?\n\nE.g. `size: \u003cT\u003e (v: T) -\u003e _ = v.length();`\n\nWhen a function parameter type is `_`, this implies a template with a\ncorresponding type parameter.\n\nA template function parameter can also be just `identifier`.\n\n```c++\nf: (x: _) = {}\ng: (x) = {} // same\n```\n### Variadic Template Functions\n\n```c++\nprint: (a0) = std::print(a0);\n\nprint: (a0, args...) = {\n    print(a0);\n    print(\", \");\n    print(args...);\n}\n\nmain: () = print(1, 2, 3);\n```\n\n\n# User-Defined Types\n\n`type` declares a user-defined type with data members and member functions.\nWhen the first parameter is `this`, it is an instance method.\n```c++\nmyclass : type = {\n    data: int = 42;\n    more: std::string = std::to_string(42);\n\n    // method\n    print: (this) = {\n        std::println(\"data: (data)$, more: (more)$\");\n    }\n\n    // non-const method\n    inc: (inout this) = data++;\n}\n\nmain: () = {\n    x: myclass = ();\n    x.print();\n    x.inc();\n    x.print();\n}\n```\nData members are `private` by default, whereas methods are `public`.\nMember declarations can be prefixed with `private` or `public`.\n\n\n## `operator=`\n\nOfficial docs: \u003chttps://github.com/hsutter/cppfront/wiki/Cpp2:-operator=,-this-\u0026-that\u003e.\n\n`operator=` with an `out this` first parameter is called for construction.\nWhen only one subsequent parameter is declared, assignment will also\ncall this function.\n\n```c++\n    operator=: (out this, i: int) = {\n        this.data = i;\n    }\n...\n    x: myclass = 99;\n    x = 1;\n```\nWith only one parameter `move this`, it is called to destroy the object:\n\n```c++\n    operator=: (move this) = {\n        std::println(\"destroying (data)$ and (more)$\");\n    }\n```\nObjects are destroyed on last use, not end of scope.\n\n\n## Inheritance\n\n```c++\nbase: type = {\n    operator=: (out this, i: int) = {}\n}\n\nderived: type = {\n    this: base = (5); // declare parent class \u0026 construct with `base(5)`\n}\n```\n\n## Type Templates\n\n * *typeTemplate*:\n   + *identifier*? `:` *templateParameterList*? `type` *requiresClause*?\n\n\n# Templates\n\n * *templateParameterList*:\n   + `\u003c` *templateParameters* `\u003e`\n * *templateParameter*\n   + *identifier* `...`? (`:` `type`)?\n   + *identifier* `:` *type*\n\nThe first parameter form accepts a type.\n\nThe second parameter form accepts a value.\nTo use a constant identifier as a template parameter,\n[enclose it in parentheses](#required-parentheses):\n```c++\nf: \u003ci: int\u003e () -\u003e _ = i;\nn: int == 5;\n...\n    std::println(f\u003c(n)\u003e());\n```\n`n` is a [constant alias](#aliases).\n\n\n## Constraints\n\n * *requiresClause*:\n   + `requires` *constExpression*\n\n```c++\ndefaultValue: \u003cT\u003e () -\u003e T requires std::regular\u003cT\u003e = { v: T = (); return v; }\n...\n    assert(defaultValue\u003cint\u003e() == 0);\n```\nNote: Using an inline concept for a type parameter is not supported yet.\n\n## Concepts\n\n* *concept*:\n  + *identifier* `:` *templateParameterList* `concept` *requiresClause*? `=` *constExpression* `;`\n\n```c++\narithmetic: \u003cT\u003e concept = std::integral\u003cT\u003e || std::floating_point\u003cT\u003e;\n...\n    assert(arithmetic\u003ci32\u003e);\n    assert(arithmetic\u003cfloat\u003e);\n```\n\n# Aliases\n\nAliases are defined using `==` rather than `=`.\n\n * *alias*:\n   + *identifier* `:` *templateParameterList*? *type*? `==` *constExpression*\n   + *identifier* `:` *templateParameterList*? *functionType* `==` *functionInitializer*\n   + *identifier* `:` *templateParameterList*? `type` `==` *type*\n   + *identifier* `:` `namespace` `==` [*identifierExpression*](#identifier-expressions)\n\nThe forms above are equivalent to the following Cpp1 declarations:\n* `constexpr` variable\n* `constexpr` function\n* `using` type alias\n* `namespace` alias\n\n```c++\n// constant template\nsize: \u003cT\u003e size_t == sizeof(T);\n// compile-time function\ninit: \u003cT\u003e () -\u003e T == ();\n\nmain: () = {\n    static_assert(size\u003cchar\u003e == 1);\n\n    // constant aliases\n    v := 5;\n    //n :== v; // error, cannot read `v` at compile-time\n    n :== 6; // OK\n    myfunc :== main;\n\n    static_assert(init\u003cint\u003e() == 0);\n    view: type == std::string_view;\n    N4: namespace == std::literals;\n}\n```\n\n\u003clink rel=\"stylesheet\" href=\"style.css\"\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fntrel%2Fcpp2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fntrel%2Fcpp2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fntrel%2Fcpp2/lists"}