# Appendix B: coming from other languages This appendix maps what you already know from C, Rust, Lisp, and Prolog onto the C++ you have now read. It is one page per language, and it uses the vocabulary of the chapter each idea belongs to. ## From C | You know | In C++ this is | |----------|----------------| | `char*` strings with a NUL terminator | `std::string` when owned, `std::string_view` when borrowed (ch10) | | Arrays that decay to pointers | `std::array`, `std::span`, `std::vector` (ch11) | | `FILE*` and manual `fclose` | an RAII wrapper whose destructor releases the handle (ch05, ch28) | | `errno` and sentinel returns | `std::expected` and exceptions (ch09, ch28) | | `printf` with unchecked format strings | `std::format` and `std::println`, checked at compile time (ch10) | | `qsort` with `void*` and a function pointer | `std::ranges::sort` with a comparator and projection (ch12) | | Manual `malloc`/`free` | `std::unique_ptr`, `std::vector`, and the Rule of Zero (ch05, ch06) | C code works in C++ through the boundary discipline of chapter 28: `extern "C"` for linkage, spans and string views for C data, and RAII wrappers for C resources. C++ retains C calling conventions, adds ownership, and replaces manual resource handling and unchecked formatting with RAII and compile‑time checked formatting. ## From Rust | You know | In C++ this is | |----------|----------------| | Value semantics | value semantics, move semantics, and copy elision (ch05, ch29) | | Ownership | a name owns a value. Ownership transfers on move (ch05) | | The borrow checker | the lifetime-safety profile, `std::span`, `std::string_view`, and `-Wlifetime-safety` (ch07) | | `Option` | `std::optional` (ch03) | | `Result` | `std::expected` (ch03, ch09) | | Enums with data | `std::variant` plus `std::visit` (ch03) | | Traits | concepts and `requires` clauses (ch17) | Rust enforces ownership and lifetimes at compile time. C++ provides the same tools but relies on the lifetime‑safety analysis and disciplined APIs (see Chapter 7). Both languages share the same mental model of ownership. The difference is where a violation is caught. ## From Lisp | You know | In C++ this is | |----------|----------------| | Macros that expand source | templates, which rewrite type patterns and are instantiated at compile time (ch16) | | Compile-time evaluation | `constexpr`, `consteval`, and the compile-time execution model (ch18) | | A domain-specific language evaluated at compile time | the constexpr SQL capstone (ch22) | | Functions as data | lambdas, `std::function`, and type erasure (ch14) | | Recursive macros / term rewriting | template metaprogramming and pack expansion (ch16, ch21) | C++ templates and constexpr supply compile‑time code generation analogous to Lisp macros. Lisp rewrites source text. C++ rewrites type patterns and evaluates a restricted subset of the language at compile time. ## From Prolog | You know | In C++ this is | |----------|----------------| | Unification | template argument deduction, which binds type parameters to concrete types (ch16) | | Goal ordering / most specific rule | overload resolution and concept subsumption (ch17) | | A term with a tag and arguments | `std::variant` plus `std::visit` (ch03) | | Backtracking search | Not in the language. Express it explicitly with recursion or a search loop | The strongest analogy is deduction: Prolog unifies a query against rules, and C++ unifies a call against template patterns and selects the most specific viable match. Chapter 17 frames concept subsumption in exactly these terms. The difference is control. Prolog searches for a solution and can backtrack. C++ resolves a call once at compile time and does not search at runtime. The shared idea is pattern matching against a set of rules, with the most specific rule winning.