Menu
Coddy logo textTech

Şablon Özelleştirme

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

Bazen genel bir şablon her tür için iyi çalışmaz. Örneğin, C stili dizeleri > ile karşılaştırmak, gerçek metni değil, işaretçi adreslerini karşılaştırır. Şablon özelleştirme (Template specialization), diğer her şey için genel sürümü korurken belirli türler için özel bir uygulama sunmanıza olanak tanır.

Bir tam özelleştirme (full specialization), belirli bir tür için tüm şablonun yerini alır. Bunu boş bir şablon parametre listesi ile bildirirsiniz ve somut türü belirtirsiniz:

// Birincil şablon
template <typename T>
class Printer {
public:
    void print(T value) {
        std::cout << value << std::endl;
    }
};

// const char* için tam özelleştirme
template <>
class Printer<const char*> {
public:
    void print(const char* value) {
        std::cout << "String: " << value << std::endl;
    }
};

Printer<int> intPrinter;
intPrinter.print(42);           // Çıktı: 42

Printer<const char*> strPrinter;
strPrinter.print("hello");      // Çıktı: String: hello

Fonksiyon şablonları da özelleştirilebilir:

template <typename T>
bool isEqual(T a, T b) {
    return a == b;
}

template <>
bool isEqual<const char*>(const char* a, const char* b) {
    return std::strcmp(a, b) == 0;
}

isEqual(5, 5);              // Genel sürümü kullanır
isEqual("hi", "hi");        // Özelleştirilmiş sürümü kullanır

Derleyici her zaman en spesifik eşleşmeyi tercih eder; kullanılan tam tür için bir özelleştirme (specialization) mevcutsa, genel şablon (generic template) yerine bu seçilecektir.

challenge icon

Görev

Kolay

Şablon özelleştirmenin (template specialization), diğer her şey için genel bir geri dönüş mekanizmasını korurken belirli türler için davranışı nasıl özelleştirmenize olanak tanıdığını gösteren, türe duyarlı bir biçimlendirici (formatter) sistemi oluşturalım.

Şablon kodunuzu düzenlemek için iki dosya oluşturacaksınız:

  • Formatter.h: Değerleri görüntülemek üzere biçimlendiren Formatter adında bir sınıf şablonu tanımlayın. Genel şablonunuz her türle çalışmalıdır, ancak özel işlem gerektiren türler için özelleştirilmiş sürümler de oluşturacaksınız.

    Birincil Formatter şablonu şunlara sahip olmalıdır:

    • T türünde bir değer alan ve şunu yazdıran bir format() yöntemi: Value: <value>

    1 veya 0 yerine insan tarafından okunabilir metin yazdıran bool için tam bir özelleştirme oluşturun:

    • format() yöntemi şunu yazdırmalıdır: Boolean: true veya Boolean: false

    Dizelerin etrafına tırnak işaretleri ekleyen const char* için tam bir özelleştirme oluşturun:

    • format() yöntemi şunu yazdırmalıdır: String: "<value>"

    Ayrıca, aynı türden iki değer alan ve bunları birlikte şu şekilde yazdıran formatPair adında bir fonksiyon şablonu oluşturun: Pair: [<first>, <second>]

    Her dizeyi tırnak içine alan const char* için bir formatPair özelleştirmesi oluşturun: Pair: ["<first>", "<second>"]

  • main.cpp: Dört girdi okuyun (her biri ayrı bir satırda):
    1. Bir tam sayı (integer)
    2. Bir ondalıklı sayı (double)
    3. Dize olarak bir boolean ("true" veya "false")
    4. Bir dize değeri

    Uygun Formatter nesneleri oluşturarak ve her tür için format() yöntemini çağırarak biçimlendiricilerinizi gösterin:

    1. Formatter<int> kullanarak tam sayıyı biçimlendirin
    2. Formatter<double> kullanarak ondalıklı sayıyı biçimlendirin
    3. Formatter<bool> kullanarak boolean değerini biçimlendirin (önce dize girdisini bir bool değerine dönüştürün)
    4. Formatter<const char*> kullanarak dizeyi biçimlendirin

    Ardından fonksiyon şablonu özelleştirmesini gösterin:

    1. İki tam sayı ile formatPair fonksiyonunu çağırın: 10 ve 20
    2. İki C-dizesi ile formatPair fonksiyonunu çağırın: "hello" ve "world"

Örneğin, 42, 3.14, "true" ve "Hello" girdileriyle:

Value: 42
Value: 3.14
Boolean: true
String: "Hello"
Pair: [10, 20]
Pair: ["hello", "world"]

Genel şablonun tam sayıları ve ondalıklı sayıları aynı şekilde nasıl işlediğine, bool ve const char* için özelleştirilmiş sürümlerin ise nasıl özel biçimlendirme sağladığına dikkat edin. Derleyici, kullandığınız her tür için otomatik olarak en spesifik eşleşmeyi seçer.

Kopya kağıdı

Şablon özelleştirme (template specialization), diğer tüm türler için genel bir sürümü korurken, belirli türler için özel uygulamalar sağlamanıza olanak tanır.

Tam Özelleştirme Sözdizimi

Boş bir şablon parametre listesi template <> ile bir özelleştirme bildirin ve somut türü belirtin:

// Primary template
template <typename T>
class Printer {
public:
    void print(T value) {
        std::cout << value << std::endl;
    }
};

// Full specialization for const char*
template <>
class Printer<const char*> {
public:
    void print(const char* value) {
        std::cout << "String: " << value << std::endl;
    }
};

Fonksiyon Şablonu Özelleştirme

Fonksiyon şablonları da özelleştirilebilir:

template <typename T>
bool isEqual(T a, T b) {
    return a == b;
}

template <>
bool isEqual<const char*>(const char* a, const char* b) {
    return std::strcmp(a, b) == 0;
}

Derleyici Seçimi

Derleyici her zaman en spesifik eşleşmeyi tercih eder - eğer kullanılan tam tür için bir özelleştirme mevcutsa, genel şablona göre bu tercih edilecektir.

Kendin dene

#include <iostream>
#include <string>
#include "Formatter.h"

using namespace std;

int main() {
    // Girdileri oku
    int intVal;
    double doubleVal;
    string boolStr;
    string strVal;
    
    cin >> intVal;
    cin >> doubleVal;
    cin >> boolStr;
    cin >> strVal;
    
    // Dizeyi bool değerine dönüştür
    bool boolVal = (boolStr == "true");
    
    // TODO: Formatter<int> oluştur ve tam sayıyı formatla
    
    // TODO: Formatter<double> oluştur ve ondalıklı sayıyı formatla
    
    // TODO: Formatter<bool> oluştur ve boolean değerini formatla
    
    // TODO: Formatter<const char*> oluştur ve dizeyi formatla
    // İpucu: const char* elde etmek için strVal.c_str() kullanın
    
    // TODO: formatPair fonksiyonunu iki tam sayı ile çağır: 10 ve 20
    
    // TODO: formatPair fonksiyonunu iki C-dizesi ile çağır: "hello" ve "world"
    
    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