विषय पर बढ़ें

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

C++17 वेरिएबल टेम्प्लेट्स

C++那些事 - वेरिएबल टेम्प्लेट्स

टेम्प्लेट कोड लिखते समय हमें अक्सर विभिन्न type traits परिभाषित और उपयोग करने की ज़रूरत पड़ती है। इन type traits का उपयोग प्रायः compile समय पर प्रकार का निर्णय करने के लिए होता है, STL द्वारा प्रदान किए गए std::is_const, std::is_same और std::is_reference ऐसे ही उदाहरण हैं। इन traits के ज़रिए डेवलपर प्रकार के गुणों के आधार पर compile-समय के निर्णय ले सकते हैं।

इस लेख में पेश किया जाएगा कि C++14 वेरिएबल टेम्प्लेट्स (variable templates) की मदद से type traits लिखना कैसे सरल हो जाता है, साथ ही एक सरल उदाहरण दिया जाएगा।

C++11

C++11 में, type trait लिखने के लिए प्रायः struct या std::integral_constant का उपयोग करके बूलियन वैल्यू को समेटना पड़ता था। उदाहरण के लिए, हमें एक ऐसा type trait is_float लिखना है जो बताए कि प्रकार float है या नहीं, इसे इस तरह लागू किया जा सकता है:

template <typename T>
struct is_float {
    static constexpr bool value = std::is_same<T, float>::value;
};

या थोड़ा अधिक संक्षिप्त, प्रकार उपनाम (type alias) और std::integral_constant का उपयोग करके:

template <typename T>
using is_float = std::integral_constant<bool, std::is_same<T, float>::value>;

यद्यपि यह सीधे struct के उपयोग से अधिक संक्षिप्त है, अंत में हम फिर भी एक प्रकार परिभाषित कर रहे हैं, बूलियन वैल्यू सीधे नहीं मिलती। इस trait का उपयोग करने के लिए, ::value मेंबर से बूलियन वैल्यू लेनी पड़ती है:

template <typename T>
void test(T t){
    if (is_float<T>::value){
        std::cout << "I'm a float" << std::endl;
    } else {
        std::cout << "I'm not a float" << std::endl;
    }
}

यह तरीका काम तो करता है, लेकिन दो कमियाँ हैं: 1. हर बार type trait का उपयोग करते समय ::value तक पहुँचना पड़ता है। 2. नया type trait परिभाषित करते समय नया प्रकार या प्रकार उपनाम घोषित करना पड़ता है, जिससे कोड की बचत बढ़ती है।

C++14 में वेरिएबल टेम्प्लेट्स का आगमन

C++14 में वेरिएबल टेम्प्लेट्स पेश हुए, जो प्रकार पर निर्भर वेरिएबल सीधे परिभाषित करने की अनुमति देते हैं। इस विशेषता ने type traits लिखना सरल कर दिया, अब हमें बूलियन वैल्यू समेटने के लिए प्रकार उपनाम या struct की ज़रूरत नहीं, बूलियन वैल्यू सीधे परिभाषित कर सकते हैं।

इसे दोबारा लिखा हुआ is_float trait इस प्रकार है:

template <typename T>
constexpr bool is_float = std::is_same<T, float>::value;

यह तरीका अधिक संक्षिप्त और स्पष्ट दिखता है, अनावश्यक कोड हट जाता है। उपयोग भी अधिक सुविधाजनक है:

template <typename T>
void test(T t){
    if (is_float<T>){
        std::cout << "I'm a float" << std::endl;
    } else {
        std::cout << "I'm not a float" << std::endl;
    }
}

पहले के तरीके की तुलना में, वेरिएबल टेम्प्लेट के उपयोग के बाद, बूलियन वैल्यू तक पहुँचने के लिए ::value की ज़रूरत नहीं रह जाती, कोड अधिक संक्षिप्त और सहज हो जाता है।

वेरिएबल टेम्प्लेट्स के फ़ायदे

  1. बचत कोड में कमी: वेरिएबल टेम्प्लेट प्रकार-आधारित वेरिएबल सीधे परिभाषित करने की अनुमति देते हैं, जिससे struct या std::integral_constant से बूलियन वैल्यू समेटने वाला अनावश्यक कोड टल जाता है।
  2. पठनीयता में वृद्धि: वेरिएबल टेम्प्लेट सिंटैक्स सरल करके कोड को अधिक स्पष्ट बनाते हैं, खासकर बड़ी संख्या में type traits लिखते समय।
  3. टेम्प्लेट विशेषीकरण का समर्थन: प्रकार उपनाम टेम्प्लेट के विपरीत, वेरिएबल टेम्प्लेट का विशेषीकरण किया जा सकता है, चाहे पूर्ण विशेषीकरण हो या आंशिक। हम विशिष्ट प्रकारों के लिए समर्पित लॉजिक परिभाषित कर सकते हैं, बिना विस्तारणीयता की चिंता के।

C++17 का आगे सुधार

C++17 ने वेरिएबल टेम्प्लेट्स के अनुप्रयोग को और बढ़ाया, और हर type trait के लिए वेरिएबल टेम्प्लेट सहायक उपकरण दिए। उदाहरण के लिए, std::is_same के लिए std::is_same_v वेरिएबल टेम्प्लेट पेश किया गया, जो type trait वैल्यू तक पहुँच सरल करता है:

template <typename T>
constexpr bool is_float = std::is_same_v<T, float>;

इस तरीके से, type traits का उपयोग और अधिक संक्षिप्त हो जाता है, डेवलपर सीधे वेरिएबल टेम्प्लेट का लाभ उठा सकते हैं और हर बार ::value तक पहुँचने की ज़रूरत नहीं पड़ती।

व्यावहारिक उदाहरण

यह विशेषता व्यवहार में काफ़ी उपयोग होती है, उदाहरण के लिए: डेटाबेस में भिन्न आकार के मेमोरी ब्लॉक आवंटित करते समय, हम टेम्प्लेट के ज़रिए भिन्न प्रकारों के ब्लॉक आकार आरंभ कर सकते हैं।

template <typename T>
constexpr size_t block_size = 1024;  // 默认大小

template <>
constexpr size_t block_size<double> = 2048;  // double 类型需要更多内存

संबंधित विषय

टिप्पणियाँ