Sepuluh tahun setelah C++11, C++20 membawa perubahan terbesar berikutnya: concepts memberi nama dan pesan error yang manusiawi untuk syarat template, ranges menggantikan pasangan iterator dengan objek range yang bisa dirangkai, three-way comparison operator<=> menuliskan enam operator pembanding sekaligus, std::format memberi pemformatan bergaya Python, std::span memberi jendela tanpa salinan ke deret data, dan std::jthread menyederhanakan thread dengan join otomatis. Ditambah coroutines dan modules (masing-masing mendapat chapter terpisah karena besarnya), C++20 adalah standar yang menggeser gaya penulisan paling jauh sejak C++11. Di chapter ini kita menguji subset yang berjalan penuh pada g++ 14.2.

Program Demo Fitur C++20 #

cpp
// fitur-cpp20.cpp — C++20: concepts, ranges, format, span, jthread, dan kawan-kawan
// Kompilasi: g++ -std=c++20 -Wall -Wextra fitur-cpp20.cpp -o fitur20

#include <algorithm>
#include <atomic>
#include <compare>
#include <concepts>
#include <format>
#include <iostream>
#include <ranges>
#include <span>
#include <thread>
#include <vector>

// concepts (C++20): syarat tipe yang bisa dibaca manusia
template <typename T>
concept Angka = std::integral<T> || std::floating_point<T>;

template <Angka T>
T jumlahkan(T a, T b) {
    return a + b;
}

// three-way comparison <=>: sekali tulis, semua operator pembanding otomatis
struct Kota {
    std::string nama;
    int populasi;
    auto operator<=>(const Kota&) const = default;
};

// designated initializers: nama member ditulis eksplisit
struct Titik {
    int x = 0;
    int y = 0;
};

int main() {
    std::cout << jumlahkan(2, 3) << " " << jumlahkan(1.5, 0.25) << "\n";

    std::vector<int> nilai{5, 3, 8, 1, 4};
    std::ranges::sort(nilai);                         // algoritma constrained
    auto ganjil = nilai
        | std::views::filter([](int x) { return x % 2 == 1; })
        | std::views::transform([](int x) { return x * 10; });
    for (int x : ganjil) {
        std::cout << x << " ";
    }
    std::cout << "\n";

    Kota a{"Bandung", 2500000}, b{"Jakarta", 10500000};
    std::cout << std::boolalpha << (a < b) << "\n";   // <=> memberi < otomatis

    std::span<int> jendela(nilai);                    // view tanpa salinan
    std::cout << jendela.size() << " " << jendela[0] << "\n";

    Titik t{.x = 3, .y = 7};
    std::cout << t.x << "," << t.y << "\n";

    std::cout << std::format("format: {}\n", nilai[1]);  // std::format (C++20)

    std::atomic<int> hasil{0};
    {
        std::jthread pekerja([&hasil] {               // jthread: join otomatis
            for (int i = 1; i <= 100; ++i) {
                hasil += i;
            }
        });
    }                                                 // destructor jthread = join()
    std::cout << "hasil thread: " << hasil << "\n";
    return 0;
}

Output yang Dihasilkan:

text
5 1.75
10 30 50 
true
5 1
3,7
format: 3
hasil thread: 5050

Mari kita bedah:

  1. Baris 16-22 (concepts): concept Angka menyatakan “T adalah integral ATAU floating point”. Fungsi jumlahkan memakainya sebagai batasan template; pemanggilan jumlahkan(2,3) dan jumlahkan(1.5, 0.25) keduanya lolos, sementara jumlahkan(std::string...) akan ditolak dengan pesan “constraints not satisfied”.
  2. Baris 40-48 (ranges): std::ranges::sort(nilai) menerima container langsung — tanpa begin()/end(). Pipeline filter | transform menghasilkan 10 30 50 dari nilai ganjil (1, 3, 5) yang dikali sepuluh, tanpa container antara.
  3. Baris 25-29 (operator<=>): = default meminta compiler membuat perbandingan tiga arah; a < b bekerja otomatis membandingkan nama lalu populasi. Enam operator (<, <=, >, >=, ==, !=) lahir dari satu baris.
  4. Baris 53-54 (span): jendela menunjuk data nilai tanpa menyalin elemen; size() dan operator[] tersedia seperti container.
  5. Baris 56-57 (designated initializers): .x = 3, .y = 7 menyebut member dengan namanya — bacaan jelas dan aman terhadap salah urutan.
  6. Baris 59 (std::format): format("format: {}\n", nilai[1]) mengembalikan std::string yang sudah jadi — terpisah dari mekanisme keluaran, sehingga bisa disimpan, dicetak, atau dikirim ke jaringan.
  7. Baris 61-69 (jthread): pekerja menambahkan 1..100 ke std::atomic<int>; keluar dari blok memicu destructor jthread yang memanggil join() — tidak ada panggilan join manual dan tidak ada thread yang terlewat. Hasil deterministik: 5050.

Coroutines dan Modules: Pengantar Singkat #

Dua fitur terbesar C++20 tidak masuk program di atas karena keduanya butuh babak tersendiri. Coroutines mengizinkan fungsi berhenti sementara (co_yield, co_await) lalu melanjutkan nanti — ideal untuk deret malas, pembacaan berkas bertahap, dan kode asinkron tanpa callback bersarang. Kita praktikkan lewat std::generator (C++23) di chapter Pengantar Coroutines. Modules menggantikan header include dengan unit kompilasi export module / import — konsepnya dibahas tuntas di chapter Pengantar Modules, lengkap dengan status dukungan compiler.

C++20 sudah menjadi target default banyak proyek besar. Berikutnya kita melompat ke C++23 — standar yang mempopulerkan std::print dan std::expected, dua fitur yang paling sering muncul di kode baru.

Rujukan resmi: cppreference — fitur C++20 , cppreference — constraints dan concepts , cppreference — std::ranges .