Menu
CoddyTech

optional, variant, any

Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan C++ di Coddy. Pelajaran 89 dari 104.

C++ modern menyediakan tiga tipe kosakata dalam header <optional>, <variant>, dan <any> yang membantumu menangani nilai yang mungkin tidak ada, dapat menyimpan salah satu dari beberapa tipe, atau dapat menyimpan tipe apa pun.

std::optional<T> merepresentasikan nilai yang mungkin ada atau tidak ada. Ini cocok untuk fungsi yang mungkin gagal tanpa melempar exception:

#include <iostream>
#include <optional>
std::optional<int> findIndex(const std::string& str, char c) {
    for (size_t i = 0; i < str.size(); ++i) {
        if (str[i] == c) return i;
    }
    return std::nullopt;  // Tidak ada nilai
}
int main() {
    auto result = findIndex("hello", 'l');
    if (result.has_value()) {
        std::cout << "Found at: " << *result << "\n";  // 2
    }
}

std::variant<Types...> adalah union yang aman terhadap tipe dan menyimpan tepat satu dari tipe yang ditentukan pada waktu tertentu:

#include <iostream>
#include <variant>
#include <string>
int main() {
    std::variant<int, double, std::string> data;
    data = 42;
    std::cout << std::get<int>(data) << "\n";
    data = "hello";
    if (std::holds_alternative<std::string>(data)) {
        std::cout << std::get<std::string>(data) << "\n";
    }
}

std::any dapat menyimpan nilai dengan tipe apa pun yang ditentukan saat runtime. Gunakan std::any_cast untuk mengambil nilainya:

#include <iostream>
#include <any>
int main() {
    std::any value = 10;
    std::cout << std::any_cast<int>(value) << "\n";
    value = std::string("text");
    std::cout << std::any_cast<std::string>(value) << "\n";
}

Pilih std::optional untuk nilai yang dapat bernilai null, std::variant saat kamu mengetahui tipe yang mungkin saat compile, dan std::any hanya saat kamu benar-benar membutuhkan fleksibilitas tipe saat runtime.

challenge icon

Tantangan

Mudah

Mari buat sistem konfigurasi yang menunjukkan keunggulan tipe kosakata C++ modern. Kamu akan membuat pengelola pengaturan fleksibel yang menangani nilai yang mungkin tidak ada, dapat menampung berbagai tipe, atau memerlukan fleksibilitas tipe saat runtime.

Kamu akan mengatur kodemu dalam tiga file:

  • ConfigTypes.h: Definisikan tipe nilai konfigurasi dan fungsi pembantu.

    Buat fungsi bernama parseValue yang menerima string dan mencoba menguraikannya sebagai bilangan bulat. Jika string tersebut mewakili bilangan bulat yang valid, kembalikan bilangan bulat yang dibungkus dalam std::optional. Jika penguraian gagal (string berisi karakter nonnumerik), kembalikan std::nullopt. Sederhananya, anggap string valid jika hanya berisi digit (dan secara opsional diawali tanda minus).

    Buat juga alias tipe bernama Setting menggunakan std::variant yang dapat menampung int, double, atau std::string.

    Terakhir, buat fungsi bernama describeSetting yang menerima Setting dan mengembalikan string yang menjelaskan tipe yang ditampung serta nilainya dalam format ini:

    • Untuk int: Integer: [value]
    • Untuk double: Double: [value]
    • Untuk string: String: [value]
  • DynamicStore.h: Buat penyimpanan key-value sederhana menggunakan std::any.

    Definisikan class DynamicStore yang dapat menyimpan nilai dari tipe apa pun. Class ini harus memiliki:

    • Method set yang menerima key string dan nilai std::any, lalu menyimpannya secara internal (gunakan std::map)
    • Method get yang menerima key dan mengembalikan nilai std::any (kembalikan std::any kosong jika key tidak ada)
    • Method hasKey yang mengembalikan true jika key ada
  • main.cpp: Baca tiga input:
    1. String yang mungkin berupa angka (untuk menguji std::optional)
    2. Penanda tipe: int, double, atau string
    3. Nilai yang sesuai dengan tipe tersebut

    Tunjukkan penggunaan ketiga tipe kosakata:

    Pertama, gunakan fungsi parseValue dengan input pertama. Jika input berisi nilai, cetak Parsed: [value]. Jika kosong, cetak Parse failed.

    Kedua, buat variant Setting berdasarkan penanda tipe. Jika tipenya int, simpan nilainya sebagai bilangan bulat. Jika double, simpan sebagai bilangan desimal. Jika string, simpan sebagai string. Lalu panggil describeSetting dan cetak hasilnya.

    Ketiga, buat DynamicStore, simpan string "config_loaded" dengan key "status", lalu ambil kembali dan cetak: Status: [value]. Gunakan std::any_cast<std::string> untuk mengambil nilainya.

Contohnya, dengan input 42, int, dan 100:

Parsed: 42
Integer: 100
Status: config_loaded

Dengan input hello, double, dan 3.14:

Parse failed
Double: 3.14
Status: config_loaded

Dengan input -15, string, dan username:

Parsed: -15
String: username
Status: config_loaded

Ingat untuk menyertakan header yang sesuai: <optional>, <variant>, <any>, <string>, dan <map> jika diperlukan. Gunakan std::holds_alternative dan std::get untuk menggunakan variant-mu, serta has_value() atau konversi boolean langsung untuk memeriksa optional-mu.

Coba sendiri

#include <iostream>
#include <string>
#include <any>
#include "ConfigTypes.h"
#include "DynamicStore.h"

int main() {
    // Baca tiga input
    std::string input1;  // String yang mungkin berupa angka (untuk menguji std::optional)
    std::string typeIndicator;  // Penanda tipe: int, double, atau string
    std::string value;  // Nilai yang sesuai dengan tipe tersebut
    
    std::cin >> input1;
    std::cin >> typeIndicator;
    std::cin >> value;
    
    // TODO: Bagian 1: Uji std::optional dengan parseValue
    // Gunakan fungsi parseValue dengan input1
    // Jika berisi nilai, cetak "Parsed: [value]"
    // Jika kosong, cetak "Parse failed"
    
    
    // TODO: Bagian 2: Uji std::variant dengan Setting
    // Buat variant Setting berdasarkan typeIndicator
    // Jika tipenya "int", simpan nilai sebagai bilangan bulat
    // Jika tipenya "double", simpan nilai sebagai double
    // Jika tipenya "string", simpan nilai sebagai string
    // Lalu panggil describeSetting dan cetak hasilnya
    
    
    // TODO: Bagian 3: Uji std::any dengan DynamicStore
    // Buat DynamicStore
    // Simpan string "config_loaded" dengan kunci "status"
    // Ambil nilainya dan cetak: "Status: [value]"
    // Gunakan std::any_cast<std::string> untuk mengambil nilainya
    
    
    return 0;
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Object

Latihan sendiri: Compiler C++ online