diff --git a/blog/2026-03-10-rust-vs-cpp-1/images/cpp.png b/blog/2026-03-10-rust-vs-cpp-1/images/cpp.png new file mode 100644 index 0000000..9d6b370 Binary files /dev/null and b/blog/2026-03-10-rust-vs-cpp-1/images/cpp.png differ diff --git a/blog/2026-03-10-rust-vs-cpp-1/images/rustacean.png b/blog/2026-03-10-rust-vs-cpp-1/images/rustacean.png new file mode 100644 index 0000000..866412d Binary files /dev/null and b/blog/2026-03-10-rust-vs-cpp-1/images/rustacean.png differ diff --git a/blog/2026-03-10-rust-vs-cpp-1/index.mdx b/blog/2026-03-10-rust-vs-cpp-1/index.mdx new file mode 100644 index 0000000..cd5fa16 --- /dev/null +++ b/blog/2026-03-10-rust-vs-cpp-1/index.mdx @@ -0,0 +1,219 @@ +--- +title: "Rust vs C++" +description: "Rust trifft auf modernes C++: Ternary Twist" +authors: + - oliverwith +tags: [rust, c++] +image: ./images/rustacean.png +--- + + + +# Rust trifft auf modernes C++ + +*Oder: Wie zwei Entwickler entdecken, dass sie mehr gemeinsam haben als gedacht* + +Es ist Montagnachmittag in der Cafeteria. Sarah, frisch von einem Rust-Projekt zurück, trifft auf Marco, der gerade sein Legacy-Projekt auf C++20 portiert hat. Beide sind in bester Diskutierlaune. + +{/* truncate */} +--- + +## Der Ternary-Twist + +**Marco:** "Rust hat nicht mal einen Ternary-Operator! Den hat sogar C!" + +**Sarah:** "Brauchen wir auch nicht." + +```rust +// Rust: if ist eine Expression +let timeout = if temperature > 150 { 5000 } else { 100 }; +``` + +**Marco:** "Okay, schön. Wir haben das aber kürzer:" + +```cpp +// C++: Der klassische ternary +auto timeout = temperature > 150 ? 5000 : 100; +``` + +**Sarah:** "Und was machst du bei sowas?" + +```rust +let retries = match (production, critical) { + (true, true) => 5, + (true, false) => 3, + (false, _) => 1, +}; +``` + +**Marco:** "Äh... verschachtelte ternaries? Oder ein immediately invoked lambda?" + +```cpp +auto retries = [&]() { + if (production && critical) return 5; + if (production) return 3; + return 1; +}(); +``` + +**Sarah:** "Ein Lambda das du sofort aufrufst? Ernsthaft?" + +**Marco:** "Hey, C++ kann alles! Nur... manchmal etwas umständlich." + +### Fazit + +Der Ternary ist ganz nett für simple Fälle. Aber weil in Rust `if`-Statements Expressions sind, braucht es dieses Extrakonstrukt gar nicht. + + +### Exkurs: Expression vs. Statement in Rust + +**Der fundamentale Unterschied:** +- **Expression** = wird zu einem Wert ausgewertet (z.B. `5 + 3`, `if x { 10 } else { 20 }`) +- **Statement** = führt eine Aktion aus, hat keinen Wert (z.B. `let x = 5;`) + +**Die magische Rolle des Semikolons:** +```rust +// Expression: Gibt einen Wert zurück +let x = { + 5 + 3 // Kein Semikolon → Expression, ergibt 8 +}; + +// Statement: Gibt () zurück +let y = { + 5 + 3; // Mit Semikolon → Statement, y hat Typ () +}; +``` + +Salopp gesagt, degradiert in Rust das Semikolon eine Expression zum Statement. Deshalb funktioniert: +```rust +fn add(a: i32, b: i32) -> i32 { + a + b // Expression, wird zurückgegeben +} + +fn add(a: i32, b: i32) -> i32 { + a + b; // Statement, gibt () statt i32 zurück +} +``` + +Das ist auch der Grund, warum `if`, `match`, `loop` und sogar Blöcke `{}` in Rust Werte zurückgeben können – sie sind alle Expressions. In C++ sind das Statements, weshalb man ein Extrakonstrukt wie den ternary operator braucht. + + +--- + + +## Slices und Ranges – Elegant auf Teilstücke zugreifen + +**Sarah:** "Lass uns mal über Slices reden. Slices sind extrem praktisch, um einen Ausschnitt aus einer Datenstruktur auszuleihen." + +**Marco:** "Wir haben seit C++20 auch Ranges! Endlich lazy evaluation." + +**Sarah:** "Zeig mal." + +### Das Problem: Ein Teilstück eines Arrays verarbeiten + +Szenario: Wir haben einen Container, zum Beispiel einen Vektor mit Zahlen, und wollen nur einen Teil davon verarbeiten ohne eine Kopie des Containers zu erstellen. +Der Verarbeitungsschritt ist im Beispiel alle ungeraden Zahlen zwischen Index 2 und 7 aufsummieren + +### Rust: Slices + +Slices sind ein fix eingebautes Feature des Sprachumfangs von Rust + +```rust +fn main() { + let data = vec![1, 2, 3, 5, 7, 8, 11, 13, 16, 20]; + + // Slice: Nimm Elemente von Index 2 bis 7 (exklusiv) + let slice = &data[2..7]; + + // Summiere ungerade Zahlen + let sum: i32 = slice.iter() + .filter(|&&n| n % 2 != 0) + .sum(); + + println!("Summe der ungeraden: {}", sum); +} +``` + +**Sarah:** "Direkte Syntax: `&data[2..7]`. Fertig." + +### C++: Ranges oder Iteratoren + +```cpp +#include +#include +#include + +int main() { + std::vector data = {1, 2, 3, 5, 7, 8, 11, 13, 16, 20}; + + // Variante 1: Mit ranges (C++20, braucht -std=c++20) + auto slice_ranges = data | std::views::drop(2) | std::views::take(5); + auto odd_ranges = slice_ranges + | std::views::filter([](int n) { return n % 2 != 0; }); + + int sum_ranges = 0; + for (auto n : odd_ranges) { + sum_ranges += n; + } + std::cout << "Summe ungerade (ranges): " << sum_ranges << "\n"; + + // Variante 2: Mit klassischen Iteratoren + auto slice_begin = data.begin() + 2; + auto slice_end = data.begin() + 7; + + int sum_iter = 0; + for (auto it = slice_begin; it != slice_end; ++it) { + if (*it % 2 != 0) { + sum_iter += *it; + } + } + std::cout << "Summe ungerade (iteratoren): " << sum_iter << "\n"; +} +``` + +**Marco:** "Ranges funktionieren... aber ich muss `drop(2)` und `take(5)` kombinieren." + +**Sarah:** "Warum nicht einfach `data[2..7]`?" + +**Marco:** "Das geht nicht. Wir haben keine Slice-Syntax. Dafür kann ich zwischen Ranges und Iteratoren wählen!" + +### Der Unterschied + +**Sarah:** "Der Punkt ist: Slices sind bei Rust von Anfang an eingebaut. Teil der Sprache." + +```rust +// Verschiedene Slice-Notationen +&data[2..7] // Von 2 bis 7 (exklusiv) +&data[2..] // Von 2 bis Ende +&data[..7] // Von Anfang bis 7 (exklusiv) +&data[..] // Alles +``` + +**Marco:** "Bei uns kam das mit C++20 nach. Und es braucht `-std=c++20` als Compiler-Flag." + +**Sarah:** "Und `views::drop(2) | views::take(5)` ist nicht gerade intuitiv." + +**Marco:** "Stimmt. Aber immerhin haben wir's jetzt! Und C++ kann alles... nur manchmal etwas umständlich." + +### Lazy Evaluation + +**Sarah:** "Wenigstens sind beide lazy – kein Zwischenarray wird erstellt." + +**Marco:** "Ja! Das war ein großer Fortschritt. Früher mussten wir alles kopieren." + +**Sarah:** "Okay, C++ Ranges sind definitiv eine Verbesserung." + +### Fazit + +Beide Sprachen haben Konzepte für Teilstücke von Sequenzen: +- **Rust:** Native Slice-Syntax `&data[2..7]`, Teil der Sprache seit Tag 1 +- **C++:** Ranges seit C++20 (braucht `-std=c++20`), oder klassische Iteratoren + +**Der Unterschied:** Rust hat Slices von Grund auf eingebaut mit direkter, intuitiver Syntax. C++ hat Ranges nachgerüstet – funktioniert, aber mit umständlicherer Syntax (`drop`/`take` statt direkter Range-Notation). + +**Für Legacy-Code:** C++ kann auf Iteratoren zurückfallen, die seit Jahrzehnten existieren. + +### Code Samples zu Slices + +- [C++ Beispiel bei godbolt](https://godbolt.org/z/r55oc4dea) +- [Rust Beispiel im rustplayground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=a850df5a96c7391064a781b3514025f5) diff --git a/blog/authors.json b/blog/authors.json index 74b7f04..a91dc12 100644 --- a/blog/authors.json +++ b/blog/authors.json @@ -12,7 +12,7 @@ "github": "shpendke", "sessionize": "https://sessionize.com/shpendke" } - }, + }, "joachimjabs": { "name": "Joachim Jabs", "title": "Senior DevOps Engineer & Cloud Architect", @@ -21,5 +21,18 @@ "image": "", "imageURL": "/img/authors/JoachimJabs.jpg", "page": true + }, + "oliverwith": { + "name": "Oliver With", + "title": "Senior Software Engineer", + "description": "siebesiech", + "url": "https://www.linkedin.com/in/oliver-with/", + "imageURL": "/img/authors/OliverWith.jpg", + "page": true, + "image": "", + "socials": { + "linkedin": "oliver-with", + "github": "quattervals" + } } } diff --git a/blog/tags.yml b/blog/tags.yml index e69de29..4d192d0 100644 --- a/blog/tags.yml +++ b/blog/tags.yml @@ -0,0 +1,23 @@ +kubernetes: + label: Kubernetes + permalink: /kubernetes + +architecture: + label: Architecture + permalink: /architecture + +cloud-native: + label: Cloud Native + permalink: /cloud-native + +well-architected: + label: Well-Architected + permalink: /well-architected + +rust: + label: Rust + permalink: /rust + +c++: + label: C++ + permalink: /cpp diff --git a/package-lock.json b/package-lock.json index ac4254c..b212b59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -211,7 +211,6 @@ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.46.3.tgz", "integrity": "sha512-hfpCIukPuwkrlwsYfJEWdU5R5bduBHEq2uuPcqmgPgNq5MSjmiNIzRuzxGZZgiBKcre6gZT00DR7G1AFn//wiQ==", "license": "MIT", - "peer": true, "dependencies": { "@algolia/client-common": "5.46.3", "@algolia/requester-browser-xhr": "5.46.3", @@ -350,7 +349,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", @@ -2197,7 +2195,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -2220,7 +2217,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -2330,7 +2326,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2752,7 +2747,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3772,7 +3766,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.2.tgz", "integrity": "sha512-C5wZsGuKTY8jEYsqdxhhFOe1ZDjH0uIYJ9T/jebHwkyxqnr4wW0jTkB72OMqNjsoQRcb0JN3PcSeTwFlVgzCZg==", "license": "MIT", - "peer": true, "dependencies": { "@docusaurus/core": "3.9.2", "@docusaurus/logger": "3.9.2", @@ -4548,7 +4541,6 @@ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.0.tgz", "integrity": "sha512-nDctevR9KyYFyV+m+/+S4cpzCWHqj+iHDHq3QrsWezcC+B17uZdIWgCguESUkwFhM3n/56KxWVE3V6EokrmONQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -5036,7 +5028,6 @@ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -5658,7 +5649,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.8.tgz", "integrity": "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -6015,7 +6005,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6101,7 +6090,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -6147,7 +6135,6 @@ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.46.3.tgz", "integrity": "sha512-n/NdPglzmkcNYZfIT3Fo8pnDR/lKiK1kZ1Yaa315UoLyHymADhWw15+bzN5gBxrCA8KyeNu0JJD6mLtTov43lQ==", "license": "MIT", - "peer": true, "dependencies": { "@algolia/abtesting": "1.12.3", "@algolia/client-abtesting": "5.46.3", @@ -6636,7 +6623,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -7649,7 +7635,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -7969,7 +7954,6 @@ "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", "integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10" } @@ -8379,7 +8363,6 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", - "peer": true, "engines": { "node": ">=12" } @@ -9557,7 +9540,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -14148,7 +14130,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -14726,7 +14707,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -15630,7 +15610,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -16459,7 +16438,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -16469,7 +16447,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -16525,7 +16502,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/react": "*" }, @@ -16554,7 +16530,6 @@ "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -18384,8 +18359,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "peer": true + "license": "0BSD" }, "node_modules/tsyringe": { "version": "4.10.0", @@ -18466,7 +18440,6 @@ "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -18814,7 +18787,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -19075,7 +19047,6 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -19666,7 +19637,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.5.tgz", "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/static/img/authors/OliverWith.jpg b/static/img/authors/OliverWith.jpg new file mode 100644 index 0000000..432892e Binary files /dev/null and b/static/img/authors/OliverWith.jpg differ