Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

تخصيص القوالب

جزء من قسم Object Oriented Programming في رحلة C++ على Coddy. الدرس 66 من 104.

أحيانًا لا يعمل القالب العام بشكل جيد مع كل نوع. على سبيل المثال، تؤدي مقارنة السلاسل النصية بنمط C باستخدام > إلى مقارنة عناوين المؤشرات، وليس النص الفعلي. تتيح لك تخصيص القالب توفير تنفيذ مخصص لأنواع محددة، مع الاحتفاظ بالإصدار العام لكل ما عدا ذلك.

يستبدل التخصيص الكامل القالب بأكمله لنوع محدد واحد. تُعلنه باستخدام قائمة معلمات قالب فارغة وتحدد النوع الملموس:

// القالب الأساسي
template <typename T>
class Printer {
public:
    void print(T value) {
        std::cout << value << std::endl;
    }
};

// التخصص الكامل لـ const char*
template <>
class Printer<const char*> {
public:
    void print(const char* value) {
        std::cout << "String: " << value << std::endl;
    }
};

Printer<int> intPrinter;
intPrinter.print(42);           // المخرجات: 42

Printer<const char*> strPrinter;
strPrinter.print("hello");      // المخرجات: String: hello

يمكن أيضًا تخصيص قوالب الدوال:

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);              // يستخدم النسخة العامة
isEqual("hi", "hi");        // يستخدم النسخة المتخصصة

يفضّل المترجم دائمًا المطابقة الأكثر تخصيصًا - إذا كان هناك تخصيص للنوع المحدد المستخدم بالضبط، فسيتم اختياره بدلًا من القالب generic.

challenge icon

التحدي

سهل

لنَبْنِ نظامًا لتنسيق القيم واعيًا بالأنواع، يوضّح كيف يتيح تخصيص القوالب تخصيص السلوك لأنواع محددة، مع الحفاظ على بديل generic لكل ما عدا ذلك.

ستنشئ ملفين لتنظيم كود القوالب:

  • Formatter.h: عرّف قالب class يُسمى Formatter لتنسيق القيم للعرض. يجب أن يعمل القالب generic مع أي نوع، لكنك ستنشئ أيضًا إصدارات متخصصة للأنواع التي تحتاج إلى معالجة مخصصة.

    يجب أن يحتوي قالب Formatter الأساسي على:

    • method format() يأخذ قيمة من النوع T ويطبع: Value: <value>

    أنشئ تخصيصًا كاملًا لـ bool يطبع نصًا مقروءًا بدلًا من 1 أو 0:

    • يجب أن تطبع method format(): Boolean: true أو Boolean: false

    أنشئ تخصيصًا كاملًا لـ const char* يضيف علامات اقتباس حول السلاسل:

    • يجب أن تطبع method format(): String: "<value>"

    أنشئ أيضًا قالب function يُسمى formatPair يأخذ قيمتين من النوع نفسه ويطبعهما معًا بالشكل: Pair: [<first>, <second>]

    أنشئ تخصيصًا لـ formatPair من أجل const char*، بحيث يحيط كل سلسلة بعلامات اقتباس: Pair: ["<first>", "<second>"]

  • main.cpp: اقرأ أربع قيم إدخال، كل واحدة في سطر منفصل:
    1. قيمة double
    2. قيمة Boolean على هيئة سلسلة (true أو false)
    3. قيمة سلسلة

    اعرض كيفية استخدام أدوات التنسيق لديك من خلال إنشاء كائنات Formatter مناسبة واستدعاء format() لكل نوع:

    1. نسّق العدد الصحيح باستخدام Formatter<int>
    2. نسّق قيمة double باستخدام Formatter<double>
    3. نسّق قيمة Boolean باستخدام Formatter<bool> (حوّل إدخال السلسلة إلى bool أولًا)
    4. نسّق السلسلة باستخدام Formatter<const char*>

    ثم اعرض تخصيص قالب function:

    1. استدعِ formatPair باستخدام عددين صحيحين: 10 و20
    2. استدعِ formatPair باستخدام سلسلتي C: "hello" و"world"

على سبيل المثال، مع قيم الإدخال 42 و3.14 وtrue وHello:

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

لاحظ كيف يتعامل القالب generic مع الأعداد الصحيحة وقيم double بالطريقة نفسها، بينما توفر الإصدارات المتخصصة لـ bool وconst char* تنسيقًا مخصصًا. يختار المصرّف تلقائيًا المطابقة الأكثر تحديدًا لكل نوع تستخدمه.

جرّب بنفسك

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

using namespace std;

int main() {
    // اقرأ المدخلات
    int intVal;
    double doubleVal;
    string boolStr;
    string strVal;
    
    cin >> intVal;
    cin >> doubleVal;
    cin >> boolStr;
    cin >> strVal;
    
    // حوّل السلسلة إلى bool
    bool boolVal = (boolStr == "true");
    
    // TODO: أنشئ Formatter<int> وقم بتنسيق العدد الصحيح
    
    // TODO: أنشئ Formatter<double> وقم بتنسيق العدد العشري
    
    // TODO: أنشئ Formatter<bool> وقم بتنسيق القيمة المنطقية
    
    // TODO: أنشئ Formatter<const char*> وقم بتنسيق السلسلة
    // تلميح: استخدم strVal.c_str() للحصول على const char*
    
    // TODO: استدعِ formatPair مع عددين صحيحين: 10 و 20
    
    // TODO: استدعِ formatPair مع سلسلتي C: "hello" و "world"
    
    return 0;
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming

تدرّب بنفسك: مترجم C++ عبر الإنترنت