Si vous écrivez du C++ moderne, l'essentiel du modèle mémoire de Keal vous est familier : shared_ptr partout, weak_ptr pour les cycles, des destructeurs déterministes. Ce qui disparaît, c'est le reste de la surface — pas de templates à instancier à la main, pas de résolution de surcharge, pas d'en-têtes, pas de comportement indéfini.
| Concept | C++ | Keal |
|---|---|---|
| Objet partagé | shared_ptr<T> | the default |
| Référence faible | weak_ptr<T> | weak var f: T? |
| Destructeur | ~T() { } | proc deinit() { } |
| Struct valeur | struct P { double x; }; | record P(val x: Float) |
| Template | template<class T> T f(T) | func f<T>(x: T): T |
| Concept | template<Ord T> | func f<T: Ord>(x: T) |
| Optionnel | std::optional<T> | T? |
| Lambda | [&](int x){ return x*2; } | { x -> x * 2 } |
| Exception | throw / catch | throw / catch |
| Surcharge d'opérateur | operator+ | trait Add |
| Espace de noms | namespace a { } | one flat namespace, for now |
Les génériques sont vérifiés une fois à la déclaration, puis monomorphisés. Un générique qui typecheck compile à chaque instanciation — pas de pages d'erreurs venues d'un en-tête.
Les opérateurs viennent des traits, et un nom veut dire une chose dans une portée. Cela coûte un peu d'expressivité et rend la lecture d'un site d'appel possible.
Passez un .cpp sur la ligne keal build : il compile sous c++, le C généré reste C11, et seul l'édition de liens est partagée.
deinit s'exécute à la frontière d'instruction suivante, le plus jeune d'abord — l'ordre même où une pile d'objets RAII se déroule.