Kita sudah berkenalan dengan using untuk type alias pada Section Variabel dan Tipe Data — di sana alias menyingkat std::vector<std::string> dan kawan-kawannya. Kini setelah struct, enum class, dan union masuk gudang peralatan kita, alias mendapat peran baru yang jauh lebih menarik: memberi nama domain pada tipe komposit. DaftarProduk terbaca lebih bermakna daripada std::vector<Produk>, dan Koordinat lebih menjelaskan maksud daripada Titik yang generik. Pada Chapter ini kita fokus pada alias untuk tipe yang baru saja kita pelajari, mengulang singkat perbandingan using versus typedef, dan menata ulang contoh dari chapter-chapter sebelumnya agar terbaca seperti bahasa domain masalah.
Alias untuk struct dan enum class #
Deklarasinya tetap using nama_baru = tipe_asal; — aturannya tidak berubah, hanya isi sisi kanan yang kini bisa tipe komposit. Alias boleh merujuk struct, enum class, container yang berisi struct, bahkan alias lain; compiler memperlakukan alias dan tipe asalnya sebagai tipe yang identik.
#include <iostream>
#include <string>
#include <vector>
struct Titik {
int x;
int y;
};
enum class StatusKirim { Menunggu, Dikirim, Selesai };
// Alias untuk tipe komposit
using Koordinat = Titik; // alias struct
using DaftarKoordinat = std::vector<Titik>; // alias container berisi struct
using Rute = std::vector<Koordinat>; // alias dari alias
using Status = StatusKirim; // alias enum class
const char* namaStatus(Status s) {
switch (s) {
case StatusKirim::Menunggu: return "menunggu";
case StatusKirim::Dikirim: return "dikirim";
case StatusKirim::Selesai: return "selesai";
}
return "tidak dikenal";
}
double jarakManhattan(const Koordinat& a, const Koordinat& b) {
int dx = a.x > b.x ? a.x - b.x : b.x - a.x;
int dy = a.y > b.y ? a.y - b.y : b.y - a.y;
return dx + dy;
}
int main() {
Rute rute {{0, 0}, {3, 4}, {6, 4}};
Status kondisi = Status::Dikirim;
std::cout << "Rute " << rute.size() << " titik, status pengiriman "
<< namaStatus(kondisi) << "\n";
std::cout << "Jarak titik 1-2: " << jarakManhattan(rute[0], rute[1]) << "\n";
std::cout << "Jarak titik 2-3: " << jarakManhattan(rute[1], rute[2]) << "\n";
return 0;
}Output yang Dihasilkan:
Rute 3 titik, status pengiriman dikirim
Jarak titik 1-2: 7
Jarak titik 2-3: 3Mari kita telaah apa yang terjadi pada baris-baris kode di atas:
- Baris 13-16 (
using Koordinat = Titik;dst.): empat alias untuk tipe komposit.Rutemenunjukkan alias boleh dibangun dari alias lain — compiler mengurai rantaiRute→vector<Koordinat>→vector<Titik>hingga ke tipe aslinya. - Baris 18-25 (
const char* namaStatus(Status s)): tanda tangan fungsi memakai aliasStatus, sehingga pembaca langsung tahu domainnya tanpa perlu tahu nama enum aslinya. - Baris 27-31 (
jarakManhattan): parameterconst Koordinat&— alias bekerja wajar dengan reference, pass-by-value, dan pass-by-const-reference yang kita kuasai pada Section Fungsi. - Baris 34-35:
Rute rute {{0, 0}, {3, 4}, {6, 4}};— aggregate initialization dan nested init dari chapter-chapter sebelumnya tetap berlaku apa adanya pada tipe alias, karena bagi compilerRuteadalahstd::vector<Titik>.
Perhatikan bahwa tidak ada satu pun konversi dalam program ini: rute[0] bertipe Titik, dan fungsi yang menerima const Koordinat& menerimanya tanpa protes — bukti nyata bahwa alias hanyalah nama kedua.
typedef: Sisipan Perbandingan #
Pada Section Variabel dan Tipe Data kita sudah menaruh kesimpulan pentingnya: typedef adalah bentuk lama yang maknanya identik dengan using, tetapi using terbaca dari kiri ke kanan dan hanya using yang bisa dibuat generik (alias template). Pada tipe komposit, keunggulan keterbacaan using makin terasa:
typedef Titik* PtitikLama; // gaya lama: nama alias tersembunyi di tengah
using PtitikBaru = Titik*; // gaya modern: "PtitikBaru adalah Titik*"
typedef int Matriks[3][3]; // typedef pada array terasa rumit
using Matriks2 = int[3][3]; // versi using terbaca kiri ke kanan
Kedua pasangan di atas menghasilkan tipe yang persis sama di mata compiler. Kita tetap perlu membaca typedef karena banyak header lama memakainya, tetapi untuk kode yang kita tulis sendiri, using adalah pilihan baku.
Alias Memperjelas Domain #
Peran terbaik alias pada tipe komposit adalah menyandikan maksud bisnis ke dalam nama tipe. Beberapa pola yang layak dijadikan kebiasaan:
- Nama koleksi yang bermakna:
DaftarProduk,Rute,KamusHarga— jauh lebih informatif daripadastd::vector<Produk>yang muncul berulang di sepuluh tanda tangan fungsi. - Nama peran domain:
KoordinatuntukTitikpada kode grafik,UangCentsuntuklong longpada kode pembayaran — satu nama, satu konteks pemakaian. - Gerbang perubahan: bila
Produkberganti menjadiProdukResmidengan field berbeda, cukup satu baris alias yang disunting dan seluruh penggunaanDaftarProdukikut berubah pada kompilasi berikutnya. - Menyembunyikan detail platform: alias seperti
std::size_tdi standard library memakai pola yang sama, sehingga kode kita portabel tanpa menyebut tipe unsigned panjangnya secara eksplisit.
Alias juga menyederhanakan tipe bertingkat dari Chapter Nested Struct: bila Mahasiswa::Alamat dirasa panjang, satu baris using AlamatMhs = Mahasiswa::Alamat; menyingkat seluruh pemakaiannya di luar struct. Bedakan pula dua peran yang bersebelahan ini: struct mendefinisikan tipe baru dengan pemeriksaan tipe sendiri, alias hanya memberi nama baru untuk tipe yang sudah ada — pemilihan di antara keduanya adalah keputusan desain, bukan soal rasa.
Referensi resmi untuk deklarasi alias dapat dibaca pada halaman type alias di cppreference. Chapter penutup Section ini menyingkap fitur yang membuat struct dan pasangan nilai makin enak dipakai: structured bindings, cara mengurai isi struct menjadi beberapa variabel dalam satu baris.