Skip to content

The C++20 Revolution

C++20 is the biggest update since C++11, introducing features that fundamentally change how we write code.

Concepts: Constraining Templates

Concepts allow you to specify requirements for template arguments. This produces much better error messages than "template substitution failure" (SFINAE).

#include <concepts>

// Only accepts integral types (int, long, etc.)
template <std::integral T>
T add(T a, T b) {
    return a + b;
}

// add(10, 20);    // OK
// add(1.5, 2.5);  // Error: double is not integral

You can define your own concepts:

1
2
3
4
template <typename T>
concept Hashable = requires(T a) {
    { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
};

Ranges: Pipeable Algorithms

The Ranges library allows you to compose algorithms using the pipe operator (|), similar to Unix shells. It also handles "views" (lazy evaluation).

#include <ranges>
#include <vector>
#include <iostream>

namespace views = std::views;

int main() {
    std::vector<int> nums = {1, 2, 3, 4, 5, 6};

    auto results = nums 
                 | views::filter([](int n){ return n % 2 == 0; }) // Keep evens
                 | views::transform([](int n){ return n * n; });  // Square them

    for (int n : results) {
        std::cout << n << " "; // 4 16 36
    }
}

Modules: Goodbye Header Files

Modules promise faster build times and better isolation by replacing the textual inclusion of header files (#include).

1
2
3
4
5
6
// math.cppm (Module Interface)
export module math;

export int add(int a, int b) {
    return a + b;
}
1
2
3
4
5
6
// main.cpp
import math;

int main() {
    add(1, 2);
}

Note: Compiler support for modules is still maturing.

Coroutines

Coroutines allow functions to be suspended and resumed. They are the foundation for async programming (generators, tasks).

  • co_await: Suspend execution until a task is done.
  • co_yield: Return a value and suspend (generator).
  • co_return: Finish the coroutine.
1
2
3
4
5
6
// Simple Generator Example (Conceptual)
Generator<int> range(int start, int end) {
    for (int i = start; i < end; ++i) {
        co_yield i;
    }
}

Three-way Comparison (<=>)

Also known as the "Spaceship Operator". It automatically generates ==, !=, <, <=, >, >=.

#include <compare>

struct Version {
    int major;
    int minor;
    int patch;

    // Default implementation compares members in order
    auto operator<=>(const Version&) const = default;
};

// Version{1, 0, 0} < Version{1, 0, 1} // true

std::format

A type-safe, fast, and extensible alternative to printf and iostreams. Inspired by Python's f-strings.

1
2
3
4
5
6
7
#include <format>
#include <iostream>

int main() {
    std::string s = std::format("Hello, {}! The answer is {}.", "World", 42);
    std::cout << s;
}

Other Features

  • consteval: Functions that must run at compile-time.
  • std::span: Non-owning view of contiguous memory.
  • jthread: Auto-joining thread (stops on destruction).