devnotes.

Modern C++ Features Overview (C++11–C++23)

Beyond auto, lambdas, and smart pointers (already covered), each C++ standard since 2011 has added features that make code shorter, safer, or both.

// C++17: structured bindings — unpack a pair/tuple/struct into named variables
std::map<std::string, int> ages = {{"Rahim", 25}};
for (const auto &[name, age] : ages) {          // no more .first / .second
    std::cout << name << " is " << age << "\n";
}

// C++17: std::optional — represents a value that might not exist
std::optional<int> findUser(int id) {
    if (id == 1) return 42;
    return std::nullopt;                          // no valid value
}
if (auto result = findUser(1)) {
    std::cout << *result << "\n";
}

// C++20: concepts — constrain what types a template accepts, with a clear error message
template <typename T>
concept Numeric = std::is_arithmetic_v<T>;

template <Numeric T>
T square(T x) { return x * x; }   // only compiles for actual numeric types

Structured bindings (C++17) unpack a std::pair, std::tuple, or simple struct directly into named variables in one line — much clearer than repeatedly writing .first/.second or std::get<0>(...).

std::optional<T> (C++17) represents "a T, or nothing" without resorting to a sentinel value (like -1 or nullptr) that could be confused with a real result — it's the idiomatic way to express "this function might not find anything" cleanly and safely. std::variant<T1, T2, ...> (C++17) similarly represents "one of these specific types," a type-safe alternative to a C-style union.

Concepts (C++20) let a template declare exactly what capabilities it requires of its type parameter (Numeric T above), producing a short, readable compile error the moment an unsuitable type is used — a major usability improvement over the cryptic, deeply-nested error walls that untemplated (SFINAE-based) generic code used to produce. C++20 also introduced ranges (composable, lazy operations over sequences, in <ranges>), coroutines (co_await/co_yield for writing asynchronous code that reads sequentially), and modules (import as a faster, cleaner alternative to #include). C++23 continues the trend with std::expected (an error-aware alternative to exceptions) and std::print (<print>, a type-safe, printf-style formatting function without the format-specifier pitfalls of C's printf).

Modern C++ Features: C++11 to C++23 Overview | DevNotes