New C++20 features worth trying right now

New C++20 features worth trying right now

As of 2026, C++20 has been a stable standard for several years, and most modern compilers (GCC 11+, Clang 10+, MSVC 2019 16.11+) support it at a level sufficient for real-world projects. In this article, we’ll look at the C++20 features that are truly worth starting to use right now — they significantly simplify code, make it safer, and faster to write.

We won’t list everything — only the most practical and useful features for everyday work.

1. Concepts — the strongest new feature of C++20

Concepts allow you to constrain templates so that the compiler gives clear, human-readable errors instead of 10-page template monstrosities.

Example before C++20:

template<typename T>
void print(T value) {
    std::cout << value << "\n";
}

After C++20 with concepts:

template<typename T>
concept Printable = requires(T t) {
    std::cout << t;
};

void print(Printable auto value) {
    std::cout << value << "\n";
}

Now if you pass a type that doesn’t support << — the error will be clear and at the user level.

Useful built-in concepts (C++20):

  • std::integral
  • std::floating_point
  • std::regular
  • std::equality_comparable

2. std::span — safe view over array/vector

Instead of passing pointer + size — just pass std::span.

#include <span>

void process(std::span<const int> data) {
    for (int x : data) {
        // safe, knows the size, no out-of-bounds risk
    }
}

You can pass both std::vector and raw arrays without copying.

3. Ranges — revolution in collection processing

Ranges let you write chained operations like in functional languages, but with zero overhead.

Example:

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

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    auto even = v | std::views::filter([](int x){ return x % 2 == 0; })
                  | std::views::transform([](int x){ return x * 10; });

    for (int x : even) {
        std::cout << x << " ";  // 20 40 60 80 100
    }
}

This is lazy evaluation — nothing is copied until iteration starts.

4. std::format — finally a proper format like in Python

#include <format>

std::string message = std::format("Hello, {}! You are {} years old.", name, age);

Much safer and more convenient than std::stringstream or sprintf.

5. std::jthread — thread that joins itself

#include <thread>

std::jthread jt([]{
    // this thread automatically finishes when leaving scope
    // no explicit join() needed
});

Perfect for local background tasks.

6. std::source_location — exactly where to put logs

#include <source_location>

void log(const std::source_location& loc = std::source_location::current()) {
    std::cout << loc.file_name() << ":" << loc.line() << " - ";
}

Automatically shows file and line of the call — no macros needed.

Futuristic digital display with 'C++ 20' text on a dark background

Summary — where to start right now

  1. Start using concepts in all your templates
  2. Replace raw arrays and pointers with std::span and std::array
  3. Switch to ranges instead of old loops
  4. Use std::format instead of stringstream
  5. Replace std::thread with std::jthread where detach is not needed

These 5 features already make code cleaner, safer, and faster to write in 2026. C++20 is not the future. It’s already the standard toolkit today.

Back to blog