Differences Between C++17 and C++20
Brooks Computing Systems - Jacksonville
Visit Brooks Computing Systems
Mainframes, Desktops & Web Sites
While C++17 introduced significant quality-of-life improvements and modern container features, C++20 represents a much larger, more foundational leap. Many of the C++20 additions aim to solve deep-seated problems in the language design, particularly around generic programming, modularity, and asynchronous code.
Here is a detailed breakdown of the major differences and additions.
---
C++20 introduced several features that fundamentally change how you write generic, modular, and asynchronous code. These are the most impactful additions.
- **What it is:** Concepts allow you to define *requirements* for types used in templates. Instead of relying on complex template error messages that tell you *what* went wrong (e.g., "requires type T to be comparable"), you tell the compiler *what* you expect (e.g., "this function only accepts types that are comparable").
- **Why it matters:** Concepts dramatically improve template error messages, making code much easier to debug and read. They enforce constraints at compile time, leading to safer and more readable generic code.
- **Example:** Instead of writing a function that accepts any type `T` and hoping it works, you write `template <typename T> requires std::integral<T> void process(T value)` to ensure `T` is an integer type.
- **What it is:** Modules are a new mechanism designed to replace the limitations of the preprocessor and header files (`#include`). They allow you to package declarations and definitions into self-contained units that are compiled and linked efficiently.
- **Why it matters:** Header files often lead to "inclusion guards" and complex preprocessor macro conflicts (the "header hell"). Modules solve this by providing true encapsulation, improving compile times, and eliminating many common build system headaches.
- **What it is:** Coroutines allow you to write asynchronous code (like network requests or database calls) that *looks* synchronous. Instead of using complex callbacks or `std::future` chains, you can use `co_await` and `co_return`.
- **Why it matters:** They simplify the writing of state machines. Before coroutines, writing non-blocking code was notoriously difficult and error-prone. Coroutines make it look like you are writing sequential code, even when the execution pauses and resumes later.
- **What it is:** Ranges introduce a standardized way to view and process sequences of data. They allow you to treat a container (like `std::vector`) and a view (like a filtered subset of that vector) as a single, uniform concept.
- **Why it matters:** They simplify algorithms. Instead of writing boilerplate code like `for (auto& item : container) { ... }`, you can use a pipeline syntax (e.g., `container | std::views::filter(...) | std::views::transform(...)`) which is highly expressive and readable.
- **`std::jthread`:** A replacement for `std::thread` that automatically joins the thread when it goes out of scope, preventing resource leaks.
- **`std::format`:** A modern, type-safe, and highly efficient way to format strings, replacing the older, error-prone `printf`-style formatting or `stringstream` usage.
---
C++17 was a massive update that focused on making the existing language more robust, safer, and easier to use, particularly in areas of resource management and data handling.
Quality, Reliability & Service Consultancy for Mainframes, Desktops & Web Sites