Lambda dengan parameter bertipe eksplisit terikat pada satu tipe: lambda yang menjumlahkan int tidak bisa menerima double tanpa kita menulis versi kedua. Padahal logikanya sering kali identik — menggandakan nilai, mencocokkan teks, membandingkan dua angka — tidak peduli tipenya apa. C++14 menjawab kebutuhan itu dengan parameter auto di dalam lambda, dan C++20 melengkapinya dengan template parameter penuh. Pada Chapter ini kita menulis lambda generic untuk beberapa tipe sekaligus dan melihat hubungannya dengan template yang dibahas pada chapter berikutnya.

Parameter auto: Lambda Generic #

Deklarasi [](auto nilai) { ... } membuat compiler memperlakukan setiap pemanggilan dengan tipe berbeda sebagai instansiasi tersendiri — persis pola kerja template, tetapi ditulis tanpa tanda < >. Lambda lalu menerima int, double, atau tipe lain yang mendukung operasi di badannya.

cpp
#include <iostream>
#include <string>

int main() {
    // parameter auto: lambda generic (C++14)
    auto duakali = [](auto nilai) {
        return nilai * 2;
    };

    std::cout << "int    : " << duakali(21) << "\n";
    std::cout << "double : " << duakali(2.5) << "\n";

    // generic + std::string (operator* tidak ada, pakai fungsi lain)
    auto ulang = [](const auto& teks, int n) {
        std::string hasil;
        for (int i = 0; i < n; ++i) {
            hasil += teks;
        }
        return hasil;
    };
    std::cout << "string : " << ulang("ha", 3) << "\n";

    // template parameter lambda (C++20)
    auto ukuran = []<typename T>(const T& nilai) {
        return sizeof(nilai);
    };
    std::cout << "sizeof int    : " << ukuran(0) << "\n";
    std::cout << "sizeof double : " << ukuran(0.0) << "\n";

    return 0;
}

Output yang Dihasilkan:

text
int    : 42
double : 5
string : hahaha
sizeof int    : 4
sizeof double : 8

Mari kita telaah apa yang terjadi pada baris-baris kode di atas:

  1. Baris 6-8 ([](auto nilai)): pemanggilan duakali(21) membuat instansiasi untuk int (hasilnya 42), sedangkan duakali(2.5) membuat instansiasi untuk double (hasilnya 5). Keduanya memakai satu definisi lambda yang sama.
  2. Baris 12-19: parameter kedua lambda adalah int biasa (jumlah pengulangan), tetapi parameter pertama const auto& menerima tipe apa pun yang mendukung +=. Di sini kita sengaja memakai std::string karena operator* tidak tersedia untuknya — generalitas lambda tetap dijaga lewat operasi yang valid.
  3. Baris 22-24 ([]<typename T>(const T& nilai)): sintaks template parameter lambda dari C++20. T kini punya nama, sehingga dapat dipakai di badan lambda untuk sizeof(nilai) — instansiasi int menghasilkan 4 dan double menghasilkan 8 di platform x86-64 ini.

Parameter auto cukup untuk mayoritas kebutuhan; bentuk []<typename T> berguna ketika badan lambda perlu menyebut tipe T secara eksplisit, misalnya mendeklarasikan variabel lokal bertipe T atau meneruskan T ke template lain.

Lambda Generic sebagai Kriteria #

Kombinasi yang paling praktis di kode nyata: lambda generic dipakai sebagai kriteria pada algoritma standard library. Satu lambda dapat dipakai ulang untuk vector int maupun vector std::string tanpa salinan definisi.

cpp
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<int> angka = {4, 1, 8, 2};
    std::vector<std::string> nama = {"Dewi", "Budi", "Rina"};

    auto cetak = [](const auto& koleksi) {
        bool pertama = true;
        for (const auto& item : koleksi) {
            std::cout << (pertama ? "" : " ") << item;
            pertama = false;
        }
        std::cout << "\n";
    };

    std::sort(angka.begin(), angka.end());
    std::sort(nama.begin(), nama.end());

    cetak(angka);
    cetak(nama);

    return 0;
}

Output yang Dihasilkan:

text
1 2 4 8
Budi Dewi Rina

Mari kita telaah: Baris 9-14 mendefinisikan satu lambda cetak dengan parameter const auto& yang menerima vector tipe apa pun. Baris 16-17 mengurutkan kedua koleksi dengan std::sort — fungsi ini dipelajari tuntas pada Section Iterators dan Algorithms, untuk saat ini cukup catat bahwa ia menerima rentang iterator. Baris 19-20 memanggil cetak dua kali dengan tipe koleksi berbeda, membuktikan satu definisi melayani keduanya. Satu konteks yang layak dijelaskan: lambda cetak tanpa capture diteruskan begitu saja seperti fungsi biasa, dan pola meneruskan lambda ke algoritma akan menjadi kebiasaan harian setelah Section algorithms selesai.

Lambda generic adalah gerbang menuju pemrograman generik yang sebenarnya. Chapter berikutnya membuka pintu itu lebar-lebar: function template — konstruksi template <typename T> yang menjadi fondasi seluruh standard library dan Section Generic Programming di akhir course.