Menu
Coddy logo textTech

optional, variant, any

Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 89 / 104.

Modern C++, eksik olabilecek değerleri işlemenize, birkaç türden birini barındırmanıza veya herhangi bir türü depolamanıza yardımcı olan <optional>, <variant> ve <any> başlıklarında üç kelime dağarcığı türü sağlar.

std::optional<T>, var olabilecek veya olmayabilecek bir değeri temsil eder - bir istisna fırlatmadan başarısız olabilecek fonksiyonlar için mükemmeldir:

#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;  // Değer yok
}

int main() {
    auto result = findIndex("hello", 'l');
    if (result.has_value()) {
        std::cout << "Found at: " << *result << "\n";  // 2
    }
}

std::variant<Types...>, herhangi bir anda belirtilen türlerden tam olarak birini tutan tür güvenli bir birleşimdir:

#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, çalışma zamanında belirlenen herhangi bir türden bir değeri tutabilir. Değeri geri almak için std::any_cast kullanın:

#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";
}

Boş bırakılabilir (nullable) değerler için std::optional'ı, olası türleri derleme zamanında bildiğinizde std::variant'ı ve yalnızca çalışma zamanı tür esnekliğine gerçekten ihtiyaç duyduğunuzda std::any'yi tercih edin.

challenge icon

Görev

Kolay

Modern C++ sözlük türlerinin gücünü gösteren bir yapılandırma sistemi oluşturalım. Eksik olabilecek, farklı türleri tutabilen veya çalışma zamanında tür esnekliğine ihtiyaç duyabilecek değerleri işleyen esnek bir ayar yöneticisi oluşturacaksın.

Kodunu üç dosyaya ayıracaksın:

  • ConfigTypes.h: Yapılandırma değer türlerini ve yardımcı işlevleri tanımla.

    Bir dize alan ve bunu tamsayı olarak ayrıştırmayı deneyen parseValue adlı bir işlev oluştur. Dize geçerli bir tamsayıyı temsil ediyorsa, tamsayıyı std::optional ile sarmalanmış olarak döndür. Ayrıştırma başarısız olursa (dize sayısal olmayan karakterler içeriyorsa), std::nullopt döndür. Basitlik açısından, yalnızca rakamlar (ve isteğe bağlı olarak başta bir eksi işareti) içeriyorsa bir dizeyi geçerli kabul et.

    Setting kullanarak bir std::variant, bir int veya bir double tutabilen std::string adlı bir tür takma adı da oluştur.

    Son olarak, bir describeSetting alan ve tuttuğu türü ve değerini şu biçimde açıklayan bir dize döndüren Setting adlı bir işlev oluştur:

    • int için: Integer: [value]
    • double için: Double: [value]
    • string için: String: [value]
  • DynamicStore.h: std::any kullanarak basit bir anahtar-değer deposu oluştur.

    Her türden değeri saklayabilen bir DynamicStore sınıfı tanımla. Şunlara sahip olmalıdır:

    • Bir dize anahtarı ve bir set değeri alan ve bunları dahili olarak saklayan (bir std::any kullan) std::map yöntemi
    • Bir anahtar alan ve get değerini döndüren bir std::any yöntemi (anahtar mevcut değilse boş bir std::any döndür)
    • Anahtar mevcutsa true döndüren bir hasKey yöntemi
  • main.cpp: Üç girdi oku:
    1. Sayı olabilecek bir dize (std::optional testi için)
    2. Bir tür belirteci: int, double veya string
    3. Bu türe karşılık gelen bir değer

    Üç sözlük türünün tamamını göster:

    İlk olarak, ilk girdiyle parseValue işlevini kullan. Bir değer içeriyorsa Parsed: [value] yazdır. Boşsa Parse failed yazdır.

    İkinci olarak, tür belirtecine göre bir Setting varyantı oluştur. Tür int ise değeri tamsayı olarak sakla. double ise double olarak sakla. string ise dize olarak sakla. Ardından describeSetting işlevini çağır ve sonucu yazdır.

    Üçüncü olarak, bir DynamicStore oluştur, "config_loaded" dizesini "status" anahtarı altında sakla, ardından bu değeri alıp şu şekilde yazdır: Status: [value]. Değeri çıkarmak için std::any_cast<std::string> kullan.

Örneğin 42, int ve 100 girdileriyle:

Parsed: 42
Integer: 100
Status: config_loaded

hello, double ve 3.14 girdileriyle:

Parse failed
Double: 3.14
Status: config_loaded

-15, string ve username girdileriyle:

Parsed: -15
String: username
Status: config_loaded

Uygun başlıkları gerektiği yerde eklemeyi unutma: <optional>, <variant>, <any>, <string> ve <map>. Varyantınla çalışmak için std::holds_alternative ve std::get kullan; optional'ını kontrol etmek için has_value() veya doğrudan boolean dönüşüm kullan.

Kendin dene

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

int main() {
    // Üç girişi oku
    std::string input1;  // Bir sayı olabilecek dize (std::optional testi için)
    std::string typeIndicator;  // Tür göstergesi: int, double veya string
    std::string value;  // Bu türe karşılık gelen değer
    
    std::cin >> input1;
    std::cin >> typeIndicator;
    std::cin >> value;
    
    // TODO: Bölüm 1 - parseValue ile std::optional testi yapın
    // input1 ile parseValue fonksiyonunu kullanın
    // Eğer bir değer içeriyorsa, "Parsed: [value]" yazdırın
    // Eğer boşsa, "Parse failed" yazdırın
    
    
    // TODO: Bölüm 2 - Setting ile std::variant testi yapın
    // typeIndicator temelinde bir Setting varyantı oluşturun
    // Eğer tür "int" ise, değeri tamsayı olarak saklayın
    // Eğer tür "double" ise, değeri double olarak saklayın
    // Eğer tür "string" ise, değeri dize olarak saklayın
    // Ardından describeSetting fonksiyonunu çağırın ve sonucu yazdırın
    
    
    // TODO: Bölüm 3 - DynamicStore ile std::any testi yapın
    // Bir DynamicStore oluşturun
    // "config_loaded" dizesini "status" anahtarı altında saklayın
    // Değeri geri alın ve yazdırın: "Status: [value]"
    // Değeri çıkarmak için std::any_cast<std::string> kullanın
    
    
    return 0;
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online C++ derleyicisi