### Hello World in Cpp2 Source: https://github.com/hsutter/cppfront/blob/main/docs/welcome/overview.md A basic example demonstrating the Cpp2 syntax for a main function. ```cpp main: () = { std::cout << "Hello, world!\n"; } ``` -------------------------------- ### Postfix operator examples Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/common.md A collection of Cpp2 postfix operator syntax examples and their Cpp1 equivalents. ```cpp obj.f() ``` ```cpp pobj*.f() ``` ```cpp obj& ``` ```cpp val~ ``` ```cpp iter++ ``` ```cpp iter-- ``` ```cpp f( 1, 2, 3) ``` ```cpp vec[123] ``` ```cpp v.begin().. c , d > ``` ```text a < ( b > c ) , d > // ok ``` -------------------------------- ### Unified Declaration Syntax Examples Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/declarations.md Basic examples of variable declarations and type deduction in Cpp2. ```cpp a + b(); ``` ```cpp { /*...*/ return c(d) / e; } ``` ```cpp x: int = 0; ``` ```cpp x: _ = 0; ``` ```cpp x := 0; ``` ```cpp x: = 0; ``` ```cpp x : = 0; ``` -------------------------------- ### Autodiff Example Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/metafunctions.md Demonstrates the basic usage of the `@autodiff` metafunction for computing derivatives of a simple function. ```cpp ad: @autodiff type = { func: (x: double) -> (r: double) = { r = x * x; } } main: (args) = { x := 3.0; x_d := 1.0; r := ad::func_d(x, x_d); std::cout << "Derivative of 'x*x' at (x)$ is (r.r_d)$" << std::endl; } ``` -------------------------------- ### Cpp2 Precondition and Postcondition Example Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/contracts.md Demonstrates the usage of preconditions and postconditions in a Cpp2 function. Preconditions are checked before function entry, and postconditions are checked before normal return. Captures like '$' are performed on entry. ```cpp insert_at: (container, where: int, val: int) pre( 0 <= where <= container.ssize(), "position (where)$ is outside 'container'" ) post ( container.ssize() == container.ssize()$ + 1 ) = { _ = container.insert( container.begin()+where, val ); } ``` -------------------------------- ### Declare parameter kinds Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/functions.md Examples of using different parameter passing semantics like inout and forward. ```cpp append_x_to_y: ( x : i32, // an i32 I can read from (i.e., const) inout y : std::string // a string I can read from and write to ) = { y = y + to_string(x); // read x, read and write y } wrap_f: ( forward x // a generic value of deduced type I can forward ) // (omitting x's type means the same as ': _') = { global_counter += x; // ok to read x f(x); // last use: automatically does 'std::forward(x)' } ``` -------------------------------- ### Define Functions and Vectors in Cpp2 Source: https://github.com/hsutter/cppfront/blob/main/docs/welcome/hello-world.md An example showing vector initialization, function calls, and string interpolation using the Cpp2 declaration syntax. ```cpp main: () = { words: std::vector = ( "Alice", "Bob" ); hello( words[0] ); hello( words[1] ); } hello: (msg: std::string_view) = { std::cout << "Hello, (msg)$!\n"; } ``` -------------------------------- ### Perform value queries Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/expressions.md Examples of value constraints using the 'is' operator. ```cpp x is 0 ``` ```cpp x is (in(10, 20)) ``` -------------------------------- ### Build cppfront with MSVC Source: https://github.com/hsutter/cppfront/blob/main/docs/welcome/overview.md Use this command to build cppfront with MSVC. Ensure you have Visual Studio 2019 version 16.11 or higher installed. ```bash cl cppfront.cpp -std:c++20 -EHsc ``` -------------------------------- ### Regex Example Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/metafunctions.md Illustrates the use of the `@regex` metafunction to define types with regular expression members for string matching and searching. ```cpp name_matcher: @regex type = { regex := R"((\w+) (\w+))"; // for example: Margaret Hamilton regex_no_case := R"/(ab)+/i)"; // case insensitive match of "ab"+ } main: (args) = { m: name_matcher = (); data: std::string = "Donald Duck"; if args.ssize() >= 2 { data = args[1]; } // regex.match requires matches to match the entire string, from start to end result := m.regex.match(data); if result.matched { // We found a match; reverse the order of the substrings std::cout << "Hello (result.group(2))$, (result.group(1))$!\n"; } else { std::cout << "I only know names of the form: .\n"; } // regex.search finds a match anywhere within the target string std::cout << "Case insensitive match: " "(m.regex_no_case.search(\"blubabABblah\").group(0))$" << std::endl; } // Prints: // Hello Duck, Donald! // Case insensitive match: abAB ``` -------------------------------- ### Implement Statement Scope Parameters Source: https://github.com/hsutter/cppfront/wiki/Design-note:-Defaults-are-one-way-to-say-the-same-thing Example of using read-only and read-write statement scope parameters in Cpp2. ```Cpp2 main: (args) = { local_int := 42; // 'in' statement scope variable // declares read-only access to local_int via i (i := local_int) for args do (arg) { std::cout << i << "\n"; // prints 42 } // 'inout' statement scope variable // declares read-write access to local_int via i (inout i := local_int) { i++; } std::cout << local_int << "\n"; // prints 43 } ``` -------------------------------- ### Run-time Subscript Bounds Checking Example Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/safety.md Demonstrates how cppfront injects run-time checks for subscript access on vectors and spans. Shows how to manually opt-out of checks using `unchecked_subscript` when bounds are explicitly verified. ```cpp main: () = { v: std::vector = ( 1, 2, 3, 4, 5 ); s: std::span = v; idx := calc_index(s); v[idx] += 42; // unsafe, therefore run-time checked s[idx] += 84; // unsafe, therefore run-time checked // manually hoist the check and do it myself if (0 ..< v.size()).contains(idx) { unchecked_subscript(v,idx) += 42; // ok, explicit "trust me" opt-out unchecked_subscript(s,idx) += 84; // ok, explicit "trust me" opt-out } } ``` -------------------------------- ### Interoperability: Mixing C++1 and C++2 Code Source: https://context7.com/hsutter/cppfront/llms.txt Demonstrates how C++1 and C++2 code can be combined within the same file, allowing seamless interoperability. This example shows C++1 includes and a C++1 `main` function calling C++2 utility functions. ```cpp // File: mixed.cpp2 #include // Cpp1 #include // Cpp1 // Cpp2 namespace and function utils: namespace = { greet: (name: std::string_view) = std::cout << "Hello, (name)$!\n"; sum: (v: std::vector) -> int = { total := 0; for v do (x) { total += x; } return total; } } // Cpp1 main function calling Cpp2 code int main() { utils::greet("World"); auto numbers = std::vector{1, 2, 3, 4, 5}; std::cout << "Sum: " << utils::sum(numbers) << "\n"; return 0; } // Alternatively, Cpp2 main calling Cpp1 code // main: () = { // utils::greet("World"); // } ``` -------------------------------- ### Use trailing separators in C++ member initializers Source: https://github.com/hsutter/cppfront/wiki/Design-note:-Commas Shows the common C++ pattern of placing separators at the start of lines to avoid trailing delimiter issues. ```cpp mytype::mytype() : member1{ value1 } , member2{ value2 } , member2{ value3 } ``` -------------------------------- ### Interleaving Cpp1 and Cpp2 Code Source: https://github.com/hsutter/cppfront/blob/main/docs/cppfront/mixed.md This example demonstrates a valid source file where Cpp1 and Cpp2 code are mixed side-by-side and call each other directly. Cppfront processes this by translating Cpp2 to Cpp1. ```cpp2 #include // Cpp1 #include // Cpp1 N: namespace = { hello: (msg: std::string_view) = // Cpp2 std::cout << "Hello, (msg)$!\n"; // Cpp2 } // Cpp2 int main() { // Cpp1 auto words = std::vector{ "Alice", "Bob" }; // Cpp1 N::hello( words[0] ); // Cpp1 N::hello( words[1] ); // Cpp1 std::cout << "... and goodnight\n"; // Cpp1 } // Cpp1 ``` -------------------------------- ### Cpp2 Type Qualifiers Example Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/common.md Demonstrates how to use type qualifiers like 'const' and pointer syntax in Cpp2. Types are read left-to-right, with qualifiers applying to what immediately follows. ```cpp // A const pointer to a non-const pointer to a const i32 object p: const * * const i32; ``` -------------------------------- ### Print Hello World in Cpp2 Source: https://github.com/hsutter/cppfront/blob/main/docs/welcome/hello-world.md A minimal one-line program demonstrating the basic function definition syntax without requiring explicit includes. ```cpp main: () = std::cout << "Hello, world!\n"; ``` -------------------------------- ### Build hello.cpp with GCC Source: https://github.com/hsutter/cppfront/blob/main/docs/welcome/hello-world.md Compile the generated `hello.cpp` file using GCC (version 10 or higher). Ensure the `CPPFRONT_INCLUDE` path is correctly set. ```bash $ g++ hello.cpp -std=c++20 -ICPPFRONT_INCLUDE -o hello $ ./hello.exe ``` -------------------------------- ### Custom Contract Violation Handler Example Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/contracts.md This example shows how to set a custom handler for the `cpp2::default` contract group and defines a handler function that prints a message and exits. Use this to integrate with your project's error reporting. ```cpp main: () -> int = { cpp2::default.set_handler(call_my_framework&); assert(false, "this is a test, this is only a test"); std::cout << "done\n"; } call_my_framework: (msg: * const char) = { // You can do anything you like here, including arbitrary work // and integration with your current error reporting libraries, // log-and-continue, throw an exception, whatever is wanted... std::cout << "sending error to my framework... [" << msg << "]\n"; exit(0); } // Prints: // sending error to my framework... [this is a test, this is only a test] ``` -------------------------------- ### Define main function with arguments Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/common.md Demonstrates the main entry point accepting command line arguments as a cpp2::args_t object. ```cpp // Print out command line arguments, then invoke // a Qt event loop for a non-UI Qt application main: (args) -> int = { for args do (arg) { std::cout << arg << "\n"; } app: QCoreApplication = (args.argc, args.argv); return app.exec(); } ``` -------------------------------- ### Build hello.cpp with Clang Source: https://github.com/hsutter/cppfront/blob/main/docs/welcome/hello-world.md Compile the generated `hello.cpp` file using Clang (version 12 or higher). Ensure the `CPPFRONT_INCLUDE` path is correctly set. ```bash $ clang++ hello.cpp -std=c++20 -ICPPFRONT_INCLUDE -o hello $ ./hello.exe ``` -------------------------------- ### Cppfront Command Line Options: Help and Version Source: https://context7.com/hsutter/cppfront/llms.txt Display help information or the version of the cppfront compiler. ```bash cppfront -help # Print help ``` ```bash cppfront -version # Print version info ``` -------------------------------- ### C++ Unsafe Cast Example Source: https://github.com/hsutter/cppfront/wiki/Design-note:-Unsafe-code Illustrates an explicit unsafe cast in C++ syntax. ```cpp reinterpret_cast(&myspan[idx]) ``` -------------------------------- ### Using loops Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/functions.md Demonstrates while, do-while, and range-based for loops with next clauses for iteration management. ```cpp words: std::vector = ("Adam", "Betty"); i := 0; while i < words.ssize() // while this condition is true next i++ // and increment i after each loop body is run { // do this loop body std::cout << "word: (words[i])$ "; } // prints: // word: Adam // word: Betty do { // do this loop body std::cout << "** "; } next i-- // and decrement i after each loop body is run while i > 0; // while this condition is true // prints: // ** // ** for words // for each element in 'words' next i++ // and increment i after each loop body is run do (inout word) // declare via 'inout' the loop can change the contents { // do this loop body word = "[" + word + "]"; std::cout << "counter: (i)$, word: (word)$ "; } // prints: // counter: 0, word: [Adam] // counter: 1, word: [Betty] ``` -------------------------------- ### Build Cppfront with GCC Source: https://context7.com/hsutter/cppfront/llms.txt Clone the repository and build the single-file compiler using g++ with C++20 support. Ensure GCC version 10 or higher is used. ```bash git clone https://github.com/hsutter/cppfront.git cd cppfront/source g++ cppfront.cpp -std=c++20 -o cppfront ``` -------------------------------- ### Build hello.cpp with MSVC Source: https://github.com/hsutter/cppfront/blob/main/docs/welcome/hello-world.md Compile the generated `hello.cpp` file using MSVC (Visual Studio 2019 version 16.11 or higher). Ensure the `CPPFRONT_INCLUDE` path is correctly set. ```bash > cl hello.cpp -std:c++20 -EHsc -I CPPFRONT_INCLUDE > hello.exe ``` -------------------------------- ### Perform static and dynamic type queries Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/expressions.md Examples of type constraints using the 'is' operator for static and dynamic checks. ```cpp x is int ``` ```cpp ptr* is Shape ``` ```cpp x is std::vector ``` ```cpp x is std::integral ``` -------------------------------- ### Build Cppfront with Clang Source: https://context7.com/hsutter/cppfront/llms.txt Clone the repository and build the single-file compiler using clang++ with C++20 support. Ensure Clang version 12 or higher is used. ```bash git clone https://github.com/hsutter/cppfront.git cd cppfront/source clang++ cppfront.cpp -std=c++20 -o cppfront ``` -------------------------------- ### Regex Feature Reference Source: https://github.com/hsutter/cppfront/blob/main/docs/notes/regex_status.md A reference guide for supported regex syntax including character classes, assertions, and capture groups. ```APIDOC ## Regex Feature Reference ### Description This documentation outlines the supported regular expression features available in the project, categorized by character classes, assertions, and capture groups. ### Supported Character Classes and Escapes - **[a-z]**: Bracketed character class. - **[[:upper:]]**: POSIX character class. - **\g1, \g{-1}, \g{name}**: Backreferences. - **\k, \k'name', \k{name}**: Named backreferences. - **\w, \W**: Word and non-word characters. - **\s, \S**: Whitespace and non-whitespace. - **\d, \D**: Decimal digit and non-digit. - **\v, \V**: Vertical whitespace and non-vertical. - **\h, \H**: Horizontal whitespace and non-horizontal. - **\1**: Backreference to capture group. - **\N**: Any character but newline. - **\K**: Keep stuff left of \K. ### Supported Assertions - **\b**: Word boundary. - **\B**: Non-word boundary. - **\A**: Beginning of string. - **\Z**: End of string or before newline. - **\z**: End of string. - **\G**: Match at pos(). ### Capture Groups and Quoting - **(...)**: Capture groups are supported. - **Metacharacters**: Quoting supported for ^.[]$()*{}?+|\ ``` -------------------------------- ### Test Cppfront Transformation (clang++) Source: https://github.com/hsutter/cppfront/blob/main/passthrough-tests/readme.md Process the generated clang-12-libstdc++-e.cpp2 file with cppfront and then use diff to verify that the output .cpp file is identical to the input .cpp2 file. ```bash cppfront clang-12-libstdc++-e.cpp2 diff -s -Z clang-12-libstdc++-e.cpp2 clang-12-libstdc++-e.cpp ``` -------------------------------- ### Use unnamed function expressions in algorithms Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/functions.md Examples of using unnamed function syntax within standard library algorithm calls. ```cpp std::ranges::for_each( a, :(x) = std::cout << x ); std::ranges::transform( a, std::back_inserter(b), :(x) = x+1 ); where_is = std::ranges::find_if( b, :(x) = x == waldo$ ); ``` -------------------------------- ### Build Cppfront with MSVC Source: https://context7.com/hsutter/cppfront/llms.txt Clone the repository and build the single-file compiler using cl.exe with C++20 support. Ensure Visual Studio 2019 version 16.11 or higher is used. ```bash git clone https://github.com/hsutter/cppfront.git cd cppfront/source cl cppfront.cpp -std:c++20 -EHsc ``` -------------------------------- ### Build cppfront with GCC Source: https://github.com/hsutter/cppfront/blob/main/docs/welcome/overview.md Use this command to build cppfront with GCC. Requires GCC 10 or higher. ```bash g++ cppfront.cpp -std=c++20 -o cppfront ``` -------------------------------- ### Using 'this' as a Contract Group Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/contracts.md Example of using 'this' as a contract group within a class hierarchy, inheriting a base class with '.report_violation'. ```cpp function_declaration: @copyable type = { // inherits from a base class that provides '.report_violation' // ... add_initializer: (inout this, source: std::string_view) pre (!has_initializer(), "cannot add an initializer to a function that already has one") pre (parent_is_type(), "cannot add an initializer to a function that isn't in a type scope") = { /*...*/ } // ... } ``` -------------------------------- ### Cpp2 Unchecked Cast Example Source: https://github.com/hsutter/cppfront/wiki/Design-note:-Unsafe-code Demonstrates how to perform an explicit unchecked cast in Cpp2 syntax, opting out of specific checks while retaining others. ```cpp2 unchecked_cast<*PodType>(myspan[idx]&) ``` -------------------------------- ### Test Cppfront Transformation (g++) Source: https://github.com/hsutter/cppfront/blob/main/passthrough-tests/readme.md Process the generated gcc-10-libstdc++-e.cpp2 file with cppfront and then use diff to verify that the output .cpp file is identical to the input .cpp2 file. ```bash cppfront gcc-10-libstdc++-e.cpp2 diff -s -Z gcc-10-libstdc++-e.cpp2 gcc-10-libstdc++-e.cpp ``` -------------------------------- ### Define @enum Metafunction Type in C++ Source: https://context7.com/hsutter/cppfront/llms.txt Use the `@enum` metafunction to create safe, scoped enumerations with auto-incrementing values starting from 1. ```cpp // @enum: Safe scoped enumeration color: @enum type = { red; green; blue; } ``` -------------------------------- ### Build cppfront with Clang Source: https://github.com/hsutter/cppfront/blob/main/docs/welcome/overview.md Use this command to build cppfront with Clang. Requires Clang 12 or higher. ```bash clang++ cppfront.cpp -std=c++20 -o cppfront ``` -------------------------------- ### Throw, try, catch Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/functions.md Demonstrates exception handling using throw with parentheses and catch with typed parameters. ```cpp // This program will print "caught something else" main: () = { try { throw( "xyzzy" ); } catch( i: int ) { std::cout << "caught int with value " << i; } catch( _ ) { std::cout << "caught something else"; } } ``` -------------------------------- ### Using postfix operators Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/common.md Shows the Cpp2 postfix syntax compared to Cpp1 equivalents for pointer dereferencing and member access. ```cpp // Cpp1 examples, from cppfront's own source code: // address = &(*tokens)[pos + num]; // is_void = *(*u)->identifier == "void"; // Cpp2 equivalents: address = tokens*[pos + num]&; is_void = u**.identifier* == "void"; ``` -------------------------------- ### Add member function to @enum type Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/metafunctions.md Cpp2's @enum types are regular types and can have member functions. This example shows a 'flip' function for a 'janus' enum. ```cpp janus: @enum type = { past; future; flip: (inout this) == { if this == past { this = future; } else { this = past; } } } ``` -------------------------------- ### C++ Conditional Parsing Example Source: https://github.com/hsutter/cppfront/wiki/Design-note:-Unambiguous-parsing This code demonstrates how changing a preprocessor directive can alter the parse tree and compiler behavior. It requires a C++ compiler to observe the effects. ```cpp // Illustrate sema (name lookup) changing parsing in today's C++ // Note that #if 1 vs. #if 0 give totally different parse trees // https://godbolt.org/z/4Kzvz6xoP #if 1 template struct foo {}; #else constexpr int foo = 2; constexpr int a = 3; #endif int main() { foo<1,2> a; } // #if 1, gcc and Clang emit this warning: // unused variable 'a' // #if 0, gcc and Clang emit this warning: // left operand of comma operator has no effect ``` -------------------------------- ### Cppfront Command Line Options: Standard Library Source: https://context7.com/hsutter/cppfront/llms.txt Control how the standard library is made available during compilation. Use -import-std for module imports or -include-std for traditional #include directives. ```bash cppfront -import-std file.cpp2 # Make std:: available via module import ``` ```bash cppfront -include-std file.cpp2 # Make std:: available via #include ``` -------------------------------- ### Test Cppfront Transformation (MSVC) Source: https://github.com/hsutter/cppfront/blob/main/passthrough-tests/readme.md Process the generated msvc-msstl-e.cpp2 file with cppfront and then use diff to verify that the output .cpp file is identical to the input .cpp2 file. ```bash cppfront msvc-msstl-e.cpp2 diff -s -Z msvc-msstl-e.cpp2 msvc-msstl-e.cpp ``` -------------------------------- ### String Interpolation Capture Example Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/expressions.md Demonstrates capturing variable values and expressions within string literals using the `(expr)$` syntax. String literals with captures become `std::string`. ```cpp x := 0; std::cout << "x is (x)ശാല "; x = 1; std::cout << "now x+2 is (x+2)ശാല "; // prints: // x is 0 // now x+2 is 3 ``` -------------------------------- ### Chained Comparisons in C++ Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/types.md Demonstrates the use of chained comparisons, which are only valid when all operators have the same precedence and are mathematically sound (e.g., all '<=', or all '>='). This example shows a valid chain for checking if a value is within a range. ```cpp // If requested is in the range of values [lo, hi) if lo <= requested < hi { // ... do something ... } // Equivalent result to: (lo ..< hi).contains( requested ) ``` -------------------------------- ### Cppfront Command Line Options: Pure Cpp2 Mode Source: https://context7.com/hsutter/cppfront/llms.txt Compile a .cpp2 file using only Cpp2 syntax, which implies importing the standard library modules. ```bash cppfront -pure-cpp2 file.cpp2 # Allow Cpp2 syntax only (implies -import-std) ``` ```bash cppfront -p file.cpp2 # Short form of -pure-cpp2 ``` -------------------------------- ### Writing the <=> Operator for Custom Types Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/types.md Implement operator<=> for custom types to enable default memberwise comparison. If the function body is omitted, a memberwise comparison is generated. This example shows the basic structure for defining a type with comparison operators. ```cpp 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 // ... } } ``` -------------------------------- ### Reflection and Generation Capture with Prefix $ Source: https://github.com/hsutter/cppfront/wiki/Design-note:-Capture An alternative syntax for capturing in reflection and generation contexts using a prefix '$'. ```cpp $(func.name()+"_wrapper"): (forward $(func.params.first().name): _) = { do_wrapped_extra_stuff(); $(func.name())($(func.params.first().name)); } } ``` -------------------------------- ### Use lists and commas Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/common.md Illustrates list syntax using parentheses, brackets, and angle brackets with comma separators. ```cpp print: (t: T, u: U) = { std::cout << t << u << "\n"; } main: () = { array: std::array = ('A', 'B', 'C'); for (0, 1, 2) do (e) { print( e, array[e] ); } // Prints: // 0A // 1B // 2C } ``` -------------------------------- ### Invalid Nesting of Cpp1 and Cpp2 Code Source: https://github.com/hsutter/cppfront/blob/main/docs/cppfront/mixed.md This example illustrates an invalid source file attempting to nest Cpp2 code within Cpp1 and vice versa. Such nesting is not supported due to parsing and semantic ambiguities, particularly concerning features like bounds-checking. ```cpp2 #include // Cpp1 #include // Cpp1 namespace N { // Cpp1 hello: (msg: std::string_view) = // Cpp2 (ERROR here) std::cout << "Hello, (msg)$!\n"; // Cpp2 (ERROR here) } // Cpp1 main: () = { // Cpp2 auto words = std::vector{ "Alice", "Bob" }; // Cpp1 (ERROR here) N::hello( words[0] ); // ? N::hello( words[1] ); // ? std::cout << "... and goodnight\n"; // ? } // Cpp2 ``` -------------------------------- ### Using Contract Groups Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/contracts.md Demonstrates the declaration and usage of global, local, and dynamically allocated contract groups. ```cpp group_a: cpp2::contract_group = (); // a global group func: () = { group_b: cpp2::contract_group = (); // a local group group_c := new(); // a dynamically allocated group // ... assert( some && condition ); assert( another || condition ); assert( another && condition ); } ``` -------------------------------- ### Illustrate C++ Semantic Analysis Affecting Parsing Source: https://github.com/hsutter/cppfront/wiki/Design-note:-Unambiguous-parsing This example demonstrates how name lookup (semantic analysis) can influence parsing in C++. The behavior changes based on the preprocessor directives, affecting the parse tree and the program's output. It highlights the 'vexing parse' issue where the compiler must perform semantic analysis to disambiguate. ```cpp // Illustrate sema (name lookup) changing parsing in today's C++ // Note that #if 1 vs. #if 0 give totally different parse trees // https://godbolt.org/z/eoo53hxje struct a {}; #if 1 a c; #else struct c {}; #endif int main() { a b(c); if constexpr( std::is_function_v ) { std::cout << "it's a function\n"; } else { std::cout << "it's not a function\n"; } } // #if 1, prints "it's not a function" // #if 0, prints "it's a function" ``` -------------------------------- ### Using prefix operators Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/common.md Demonstrates the use of prefix operators in Cpp2, which follow the same syntax as Cpp1. ```cpp if !vec.empty() { vec.emplace_back( -123.45 ); } ``` ```cpp +100 ``` ```cpp -100 ``` -------------------------------- ### Compile C++2 to C++ using cppfront Source: https://github.com/hsutter/cppfront/blob/main/docs/welcome/hello-world.md Use the `cppfront` command-line tool with the `-p` flag to compile a `.cpp2` file into a standard C++ file. This flag ensures the C++ standard library is available. ```bash cppfront hello.cpp2 -p ``` -------------------------------- ### Using Contract Predicates Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/contracts.md Illustrates the use of static and dynamic contract predicates to conditionally evaluate contracts. ```cpp is_checked_build: bool == SEE_BUILD_FLAG; // a static (compile-time) predicate checking_enabled: bool = /*...*/ ; // a dynamic (run-time) predicate, // could change as the program runs func: () = { assert( condition ); } ``` -------------------------------- ### Initializing objects when they are declared Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/objects.md Illustrates object initialization at both type scope and function scope. ```cpp shape: type = { // An object at type scope (data member) // initialized with its type's default value points: std::vector = (); draw: (this, where: canvas) -> bool = { // An object at function scope (local variable) // initialized with color::red pen := color::red; // ... } // ... } ``` -------------------------------- ### Initializing local objects after they are declared Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/objects.md Demonstrates deferred initialization of local objects, requiring definite assignment on all execution paths. ```cpp f: () = { buf: std::array; // uninitialized // ... calculate some things ... // ... no uses of buf here ... buf = some_calculated_value; // constructs (not assigns) buf // ... std::cout << buf[0]; // ok, a has been initialized } g: () = { buf: std::array; // uninitialized if flip_coin_is_heads() { if heads_default_is_available { buf = copy_heads_default(); // constructs buf } else { buf = (other, constructor); // constructs buf } } else { load_from_disk( out buf ); // constructs buf (*) } std::cout << buf[0]; // ok, a has been initialized } load_from_disk: (out x) = { x = /* data read from disk */ ; // when `buffer` is uninitialized, } // constructs it; otherwise, assigns ``` -------------------------------- ### Using Specific Names from a Namespace Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/namespaces.md Shows how to use a 'using' statement to bring a specific name ('widget') from 'widgetlib' into the current scope, eliminating the need for explicit qualification. ```cpp // A namespace to put all the names provided by a widget library widgetlib: namespace = { widget: type = { /*...*/ } // ... more things ... } main: () = { // Explicit name qualification w: widgetlib::widget = /*...*/; { // Using the specific name, no widgetlib:: qualification needed using widgetlib::widget; w2: widget = /*...*/; // ... } { // Using the whole namespace, no widgetlib:: qualification needed using widgetlib::_; w3: widget = /*...*/; // ... } // ... } ``` -------------------------------- ### Using `inspect` for pattern matching Source: https://github.com/hsutter/cppfront/blob/main/docs/cpp2/expressions.md Shows how to use the `inspect` expression for pattern matching. It evaluates alternatives in order and returns the value of the first matching alternative's body. ```cpp // A generic function that takes an argument 'x' of any type // and inspects various things about `x` test: (x) = { forty_two := 42; std::cout << inspect x -> std::string { is 0 = "zero"; // == 0 is (forty_two) = "the answer"; // == 42 is int = "integer"; // is type int (and not 0 or 42) is std::string = x as std::string; // is type std::string is std::vector = "a std::vector"; // is a vector is _ = "(no match)"; // is something else } << "\n"; } // Sample call site test(42); // Behaves as if the following function were called: // test: (x) = { std::cout << (:std::string = "the answer") << "\n"; } // (and that's why inspect alternatives are introduced with '=') ``` -------------------------------- ### Generate Preprocessed Standard Library (MSVC) Source: https://github.com/hsutter/cppfront/blob/main/passthrough-tests/readme.md Use cl with the -std:c++latest and /E flags to preprocess the all-std.cxx file, generating a single .cpp2 file representing the MSVC STL implementation. ```bash cl all-std.cxx -std:c++latest /E > msvc-msstl-e.cpp2 ``` -------------------------------- ### Verbose Lambda Function Syntax in C++ Source: https://context7.com/hsutter/cppfront/llms.txt Illustrates the full syntax for defining lambda functions, including explicit parameter types and return types. ```cpp // Full verbose lambda syntax std::ranges::for_each(numbers, :(x: int) -> void = { std::cout << x << " "; }); ``` -------------------------------- ### Use Terse Lambda Syntax Source: https://github.com/hsutter/cppfront/wiki/Design-note:-Defaults-are-one-way-to-say-the-same-thing Demonstrates concise lambda syntax for expression-scope functions in Cpp2. ```Cpp2 std::for_each(first, last, :(x) std::cout << x;); std::transform(x.begin(), x.end(), y.begin(), :(x) x+1;); location_of_value = std::find_if(x.begin(), x.end(), :(x) x == value$;); ``` -------------------------------- ### Generate Preprocessed Standard Library (clang++) Source: https://github.com/hsutter/cppfront/blob/main/passthrough-tests/readme.md Use clang++-12 with the -std=c++2a and -E flags to preprocess the all-std.cxx file, generating a single .cpp2 file representing the libstdc++ implementation. ```bash clang++-12 all-std.cxx -std=c++2a -E > clang-12-libstdc++-e.cpp2 ``` -------------------------------- ### UFCS: Calling Non-Member Functions with Member Syntax Source: https://context7.com/hsutter/cppfront/llms.txt Demonstrates how to call non-member functions using member syntax (e.g., `x.f()`) when a member function `f` does not exist. This syntax also works with standard library functions and allows for chaining calls. ```cpp // Non-member function double_value: (x: int) -> int = x * 2; // Extension-like functions is_empty: (s: std::string) -> bool = s.size() == 0; repeat: (s: std::string, n: int) -> std::string = { result: std::string = ""; for (0 ..< n) do (_) { result += s; } return result; } main: () = { x := 21; // UFCS: x.f() calls f(x) if no member f exists result := x.double_value(); // Calls double_value(x) std::cout << "(result)$\n"; // 42 // Works with standard library functions too v: std::vector = (3, 1, 4, 1, 5); size := v.std::ssize(); // Calls std::ssize(v) // Chain UFCS calls greeting := "ha".repeat(3); // Calls repeat("ha", 3) std::cout << "(greeting)$\n"; // "hahaha" // Use ..f() to require member function only s: std::string = "hello"; len := s..size(); // Only calls member size() } ```