C+

C+ is a fast, safer,
sugarless language.

A compiled, statically typed systems language: native machine code through LLVM, no VM, no garbage collector, manual memory made safe by a borrow checker, and two-way C interop.

v0.0.30 · WinUI 3 on Windows, appenv, and Liquid Glass / Material 3 UI parity
Run in Playground ›
fn collatz_steps(start: i32) -> i32 {
    var n: i32 = start;
    var steps: i32 = 0;
    while n != 1 {
        if n % 2 == 0 { n = n / 2; } else { n = 3 *% n +% 1; }
        steps = steps +% 1;
    }
    return steps;
}

fn main() -> i32 {
    #println(collatz_steps(27));   // 111
    return 0;
}
$ cpc collatz.cplus -o collatz && ./collatz # 111 Executes directly in browser via WebAssembly

Create using C+

In practice

What the language and toolchain produce

Declarative native windows, compile-time ownership and real-time diagnostics, and a resolved code graph exposed directly by the compiler.

Declarative Native UI · Facet Full example ›
return @ui {
    column {
        label("Count: ${this.n}", key: "count",
              font_size: 20.0)
        row {
            button("+1", key: "inc-btn",
                   on_click: this.on_inc)
            button("Reset", key: "reset-btn",
                   on_click: this.on_reset)
        }.gap(8.0)
    }.padding(20.0).gap(12.0)
};
Counter NSWindow / WinUI
Real native controls
Count: 4
+1 Reset
key: "inc-btn" actionable: true

Same @ui tree lowers to AppKit, UIKit, Android Views, GTK4, and WinUI 3 with zero webview overhead.

Compile-time proof · cpc check 200 error codes ›
error[E0335]: use of moved value `buf`
  --> src/main.cplus:14:14
   |
13 |     consume(buf);      // moved here (`take` parameter)
14 |     #println(buf.len); // rejected before codegen
Compiler Code Graph · cpc query / mcp Code graph guide ›
$ cpc query callers Counter::advance
[
  { "id": "src.main::main", "file": "src/main.cplus", "line": 13 }
]

At a glance

Paradigm
Compiled, statically typed systems language
Compiles to
Native machine code via LLVM, linked with clang
Runtime
None. No VM, no garbage collector
Memory
Manual, made safe by a compile-time borrow checker
Types
Static, with inference
Errors
Result values, no exceptions
Interop
Two-way C ABI: call C, and be called by C
Platforms
macOS, Windows, Linux, iOS, Android, ESP32, and WebAssembly. Facet supplies AppKit, UIKit, Android, GTK, and WinUI 3 backends.
Tooling
cpc compiler, LSP, MCP code graph, and C bindgen

Fast

Native speed, no runtime tax.

C+ compiles directly to native code through LLVM. The borrow checker and restrict markers give the optimizer the aliasing guarantees it needs to vectorize hot loops. No annotations to remember, just the ones the type system already proved.

// noalias hot loop, vectorizes cleanly
fn axpy(n: usize, a: f32, restrict x: *f32, restrict y: *f32) {
    var i: usize = 0;
    while i < n {
        y[i] = a * x[i] + y[i];
        i = i +% 1;
    }
}

Expressive

Concise code, few ways to go wrong.

Structs, methods, generics, and pattern matching, with no overloading, no implicit conversions, and no closures to reason about. Fewer ways to write it wrong, and exact, numbered diagnostics when you do.

struct Point { x: i32, y: i32 }

impl Point {
    fn translate(ref this, dx: i32, dy: i32) {
        this.x = this.x +% dx;
        this.y = this.y +% dy;
    }
}

Safer

Why "safer," not "safe."

C+ is not a sandbox, and does not pretend to be. Raw pointers, foreign calls, and other operations that can cause undefined behaviour stay your responsibility. The difference from C is that each one is visible in the source itself (a raw-pointer dereference, a pointer cast, an extern call), so nothing dangerous hides from a reviewer. What the language does remove outright: no null, no exceptions, no uninitialized reads, and a borrow checker that enforces aliasing-xor-mutation so data races don't compile, with Drop / defer for deterministic cleanup. That is the whole claim, and the reason the word is "safer," not "safe": far fewer ways to crash by accident, and the operations that still can are the ones you can see.

struct Buf { ptr: *u8, len: usize }

impl Buf {
    // runs automatically on scope exit
    fn drop(ref this) {
        free(this.ptr);
    }
}

fn main() -> i32 {
    let b: Buf = make_buf();
    defer #println("cleaning up");
    return 0;
}
Compiler & runtime tooling

Queryable code, inspectable apps.

The cpc compiler does not throw away its type and symbol resolution after a build. It exposes the resolved code graph directly to editors, CLI scripts, and coding agents, while native Facet applications can expose a capability-granted UI surface for automated testing and control.

  • ✓ Code graph: cpc query, cpc lsp, and cpc mcp answer definitions, callers, callees, and types from one warm session
  • ✓ Fast type-check: cpc check validates without codegen; cpc build links the native binary
  • ✓ UI automation: facet_agent lets a test harness or agent inspect keyed controls and invoke actions under explicit grants
# 1. Query the compiler's resolved symbol graph
$ cpc query callers process_frame
$ cpc query context Shape::area

# 2. Type-check and borrow-check without codegen
$ cpc check --diagnostics=json

# 3. Build and run native tests
$ cpc test
Soft real-time

Deterministic by contract.

Audio callbacks, control loops, and frame hot paths can't afford a hidden allocation or a lock. Mark a function #[realtime] and the compiler proves it across the entire transitive call graph: no heap allocation, no blocking, no unbounded recursion, no unknown calls. Not a lint. A compile error.

  • ✓ #[no_alloc] · rejects any path to malloc
  • ✓ #[no_block] · rejects locks, waits, and blocking I/O
  • ✓ #[max_stack(N)] · bounded, ABI-accurate frame size
  • ✓ lock-free SPSC rings & fixed pools in vendor/rt
// compiler-checked: a violation won't compile
const GAIN: f32 = 0.5f32;

#[realtime]
fn process_frame(n: usize, restrict input: *f32x4,
        restrict output: *f32x4) {
    let gain: f32x4 = f32x4::splat(GAIN);
    var i: usize = 0;
    while i < n {
        output[i] = input[i].mul(gain);   // pure SIMD math
        i = i +% 1;
    }
    // Vec::new / lock / sleep here → E0901 / E0907
}
Two-way C ABI

Interoperable, in both directions.

C+ calls C directly through extern fn and Objective-C through typed #msg_send and #selector intrinsics, with no runtime glue layer. And because cpc emits standard C-ABI object files and C headers, existing C and C++ projects link C+ straight back: drop a .o into a CMake build and replace functions one symbol at a time, until the binary stands on its own. When wrapping a system framework by hand would mean pages of declarations, cpc-bindgen generates the C+ package from C, Objective-C, Swift, Java/JNI, and GObject/GIR interfaces.

// ① C+ calls C, no bindings
extern fn cblas_sdot(n: i32, x: *f32, ix: i32,
                     y: *f32, iy: i32) -> f32;
// ② C links C+ back, a plain C symbol
export extern fn cplus_dot(restrict a: *f32,
        restrict b: *f32, n: usize) -> f32 {
    // ... emits `cplus_dot` for clang / CMake to link
    return 0.0f32;
}

Native speed, by design

No GC, no runtime overhead. A single-threaded raytracer, release build, on Apple Silicon.

0.94s
Render time (wall-clock)
33KB
Stripped binary size
0.10s
Clean build time
2.5MB
Peak memory (max RSS)

Ray Tracing in One Weekend (10 spheres, 800×450, 32 spp, max depth 15) · Apple M1 Max, single-threaded cpc build --release · Peak memory measured as max resident set size via /usr/bin/time -l · full source & reproduction steps ›

Get started

Install the prebuilt cpc toolchain and compile your first native binary.

# 1. Install Xcode Command Line Tools (provides clang) and cpc
$ xcode-select --install
$ brew install netdur/cplus/cplus
$ cpc --version

Full host prerequisites, verification steps, and iOS / Android / ESP32 cross-compilation are on the Install page and GitHub releases.