Curiously Recurring Template Pattern در c++ - هفت خط کد انجمن پرسش و پاسخ برنامه نویسی

وبـــلاگ هــفت خــط کــد


آموزش های برنامه نویسی
۱۸۶ نفر آنلاین
۴۶ عضو و ۱۴۰ مهمان در سایت حاضرند

Curiously Recurring Template Pattern در c++

0 امتیاز
سلام.

من نمی دونم چم شده هر چقدر Curiously Recurring Template Pattern را می خونم متوجه نمیشم کسی می دونه داستانش چیه؟
سوال شده مرداد 11, 1402  بوسیله ی Lori3 (امتیاز 857)   11 37 106

1 پاسخ

+1 امتیاز
 
بهترین پاسخ

یکی از مباحث اساسی در polymorphism تغییر رفتار کلاس از طریق وراثت و override کردن متد های virtual هست .در شرایط عادی و برای مسائلی که پرفومنس اهمیت بالایی نداره استفاده از همین الگو مناسبه ولی زمانی که شما قصد داشته باشید متدهای virtual را میلیلردها بار صدا بزنید اون زمان شما پرفورمنس را از دست میدید در اینجا استفاده از polymorphism نتیجه خوبی نداره.در واقع برای مدیریت متدهای virtual کلاس از vtable استفاده میشه که از آن طریق کلاس های فرزند رفتار کلاس والد را در زمان اجرا override  می کنن .حالا فرض کنید شما امکانی داشته باشید همین override  کردن رفتار در زمان کامپایل صورت بگیره دیگه نیازی نیست در پردازش های سنگین در هر مرحله از vtable استفاده کنیم در واقع crtp توی c++ این مشکل را حل کرده. به مثال زیر توجه کنید در مثال اول با crtp سه بار متد override شده زمان کامپایل یک میلیار بار فراخوانی میشه  و یک شمارنده هم با هر بار فراخوانی به متغییر sum اضافه می کنه همین مثال با polymorphism تابع override در زمان اجرا 3 بار متد مجازی یک میلیارد فراخوانی میشه. تو این مثال crtp  از نظر محاسباتی صفر میلی ثانیه ولی polymorphism  5 ثانیه طول میکشه واقعا اختلاف فاجعه است.

#include <chrono>
#include <iostream>
using namespace std;
template <typename Derived>
class BaseCRTP
{
public:
    int64_t sum_{0};
    void interface()
    {
        static_cast<Derived*>(this)->implementation();
    }
};

class DerivedCRTP : public BaseCRTP<DerivedCRTP>
{
public:
    void implementation()
    {
        sum_++;
    }
};

class BaseVirtual
{
public:
    int64_t sum{0};
    virtual void implementation() = 0;
    void interface()
    {
        implementation();
    }
};

class DerivedVirtual : public BaseVirtual
{
public:
    void implementation() override
    {
        sum++;
        // implementation code here
    }
};

int main()
{
    const int numIterations = 1000000000;

    DerivedCRTP dCRTP;
    auto startCRTP = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < numIterations; ++i) {
        dCRTP.interface();
        dCRTP.interface();
        dCRTP.interface();
        
    }
   
    auto endCRTP = std::chrono::high_resolution_clock::now();
    auto durationCRTP = std::chrono::duration_cast<std::chrono::milliseconds>(endCRTP - startCRTP).count();
    std::cout << "CRTP: " << durationCRTP << " milliseconds" << std::endl;
     cout << "sum:" << dCRTP.sum_ << endl;

    DerivedVirtual dVirtual;
    auto startVirtual = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < numIterations; ++i) {
        dVirtual.interface();
        dVirtual.interface();
        dVirtual.interface();
    
    }
   
    auto endVirtual = std::chrono::high_resolution_clock::now();
    auto durationVirtual = std::chrono::duration_cast<std::chrono::milliseconds>(endVirtual - startVirtual).count();
    std::cout << "Virtual: " << durationVirtual << " milliseconds" << std::endl;
    cout << "sum:" << dCRTP.sum_ << endl;

    return 0;
}

 

پاسخ داده شده مرداد 11, 1402 بوسیله ی مصطفی ساتکی (امتیاز 21,998)   24 34 75
انتخاب شد مرداد 24, 1402 بوسیله ی Lori3
...