विषय पर बढ़ें

अंतिम अद्यतन:2026-10-12

C++ पॉलीमॉर्फ़िज़्म: वर्चुअल फ़ंक्शन, CRTP और variant

C++ पॉलीमॉर्फ़िज़्म परफ़ॉर्मेंस टेस्ट: CRTP vs std::variant vs virtual

पॉलीमॉर्फ़िज़्म ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग की एक महत्वपूर्ण अवधारणा है, जो एक ही इंटरफ़ेस के द्वारा भिन्न प्रकारों को दर्शाने की सुविधा देती है। C++ पॉलीमॉर्फ़िज़्म लागू करने के कई तरीके प्रदान करता है, इस लेख में तीन परिदृश्यों के पॉलीमॉर्फ़िज़्म पर चर्चा होगी:

  1. वर्चुअल फ़ंक्शन: C++ में पॉलीमॉर्फ़िज़्म लागू करने का पारंपरिक तरीका वर्चुअल फ़ंक्शन का उपयोग है। इसमें विशिष्ट implementation प्रदान करने के लिए बेस क्लास और डिराइव्ड क्लास का उपयोग किया जाता है।
  2. std::variant: C++17 में पेश हुआ std::variant बिना इनहेरिटेंस के पॉलीमॉर्फ़िज़्म लागू करता है।
  3. CRTP (Curiously Recurring Template Pattern): CRTP एक विशेष तकनीक है, जो टेम्प्लेट के विचित्र रिकर्सिव पैटर्न के ज़रिए पॉलीमॉर्फ़िज़्म लागू करती है।

टेस्ट किए गए संयोजन परिदृश्य इस प्रकार हैं:

  • केवल crtp
  • crtp + std::variant
  • virtual
  • std::variant + std::visit
  • std::variant + std::get_if
  • std::variant + std::holds_alternative

उपयोग किए गए कंपाइलर:

  • gcc 13.2
  • clang17.0

पूरा टेस्ट कोड 星球 पर रखा गया है, यहाँ मुख्य कोड दिखाया गया है

class Shape {
public:
    virtual ~Shape() = default;
    virtual double area() const = 0;
};

class Circle : public Shape
class Rectangle : public Shape



// virtual
static void BM_VirtualFunction(benchmark::State& state) {
    std::vector<std::unique_ptr<Shape>> shapes;
    shapes.reserve(1000);

    for (int i = 0; i < 1000; ++i) {
        if (i % 2 == 0) {
            shapes.emplace_back(std::make_unique<Circle>(5.0));
        } else {
            shapes.emplace_back(std::make_unique<Rectangle>(4.0, 6.0));
        }
    }

    for (auto _ : state) {
        double totalArea = 0.0;
        for (const auto& shape : shapes) {
            totalArea += shape->area();
        }
        benchmark::DoNotOptimize(totalArea);
    }
}
BENCHMARK(BM_VirtualFunction);

static void BM_VariantVisit(benchmark::State& state) {
    std::vector<std::variant<Circle, Rectangle>> shapes;
    shapes.reserve(1000);

    for (int i = 0; i < 1000; ++i) {
        if (i % 2 == 0) {
            shapes.emplace_back(Circle(5.0));
        } else {
            shapes.emplace_back(Rectangle(4.0, 6.0));
        }
    }

    for (auto _ : state) {
        double totalArea = 0.0;
        for (const auto& s : shapes) {
            totalArea += std::visit([](const auto& shape) { return shape.area(); }, s);
        }
        benchmark::DoNotOptimize(totalArea);
    }
}
static void BM_CRTPVariant(benchmark::State& state) {
    std::vector<ShapeVariant> shapes;
    shapes.reserve(1000);

    for (int i = 0; i < 1000; ++i) {
        if (i % 2 == 0) {
            shapes.emplace_back(crtp_light::Circle(5.0));
        } else {
            shapes.emplace_back(crtp_light::Rectangle(4.0, 6.0));
        }
    }

    for (auto _ : state) {
        double totalArea = 0.0;
        for (const auto& s : shapes) {
            totalArea += std::visit([](const auto& shape) { return shape.area(); }, s);
        }
        benchmark::DoNotOptimize(totalArea);
    }
}
BENCHMARK(BM_CRTPVariant);

// ...

टेस्ट परिणाम 1: gcc से कंपाइल, देखा जा सकता है कि virtual और std::variant की परफ़ॉर्मेंस में ज़्यादा अंतर नहीं है, लेकिन crtp से बहुत बड़ा अंतर है।

gcc bm

टेस्ट परिणाम 2: clang से कंपाइल, कुल मिलाकर रुझान gcc कंपाइल के समान ही है, केवल crtp + std::variant की परफ़ॉर्मेंस में स्पष्ट गिरावट दिखती है, संभवतः इसका कारण यह भी है कि यहाँ std::visit का उपयोग किया गया है।

clang bm

A Tour of C++ पुस्तक में लिखा है:

This is basically equivalent to a virtual function call, but potentially faster. As with all claims of performance, this ''potentially faster'' should be verified by measurements when performance is critical. For most uses, the difference in performance is insignificant.

यह इस टेस्ट से लगभग मेल खाता है।

संबंधित विषय

टिप्पणियाँ