C++
कटौती प्रकार
खोज…
टिप्पणियों
नवंबर 2014 में, C ++ मानकीकरण समिति ने प्रस्ताव N3922 को अपनाया, जो प्रत्यक्ष आरंभिक सिंटैक्स का उपयोग करते हुए ऑटो और ब्रेडेड इनिशियलाइज़र्स के लिए विशेष प्रकार की कटौती नियम को समाप्त करता है। यह C ++ मानक का हिस्सा नहीं है लेकिन कुछ संकलक द्वारा कार्यान्वित किया गया है।
कंस्ट्रक्टरों के लिए टेम्पलेट पैरामीटर कटौती
C ++ 17 से पहले, टेम्पलेट कटौती आपके लिए एक निर्माता में वर्ग प्रकार नहीं घटा सकती है। इसे स्पष्ट रूप से निर्दिष्ट किया जाना चाहिए। कभी-कभी, हालांकि, ये प्रकार बहुत ही बोझिल हो सकते हैं (या make_pair()
के मामले में) नाम देना असंभव है, इसलिए हमें प्रकार के कारखानों (जैसे make_pair()
, make_tuple()
, back_inserter()
, आदि का प्रसार मिला।
यह अब आवश्यक नहीं है:
std::pair p(2, 4.5); // std::pair<int, double>
std::tuple t(4, 3, 2.5); // std::tuple<int, int, double>
std::copy_n(vi1.begin(), 3,
std::back_insert_iterator(vi2)); // constructs a back_insert_iterator<std::vector<int>>
std::lock_guard lk(mtx); // std::lock_guard<decltype(mtx)>
कन्स्ट्रक्टर्स को क्लास टेम्प्लेट मापदंडों को कम करने के लिए माना जाता है, लेकिन कुछ मामलों में यह अपर्याप्त है और हम स्पष्ट कटौती गाइड प्रदान कर सकते हैं:
template <class Iter>
vector(Iter, Iter) -> vector<typename iterator_traits<Iter>::value_type>
int array[] = {1, 2, 3};
std::vector v(std::begin(array), std::end(array)); // deduces std::vector<int>
टेम्पलेट प्रकार कटौती
टेम्पलेट जेनेरिक सिंटैक्स
template<typename T>
void f(ParamType param);
f(expr);
केस 1: ParamType
एक संदर्भ या सूचक है, लेकिन एक सार्वभौमिक या अग्रेषित संदर्भ नहीं है। इस मामले में टाइप कटौती इस तरह से काम करती है। कंपाइलर संदर्भ भाग को अनदेखा करता है यदि वह expr
में मौजूद है। संकलक तो पैटर्न मैचों expr
के खिलाफ की प्रकार ParamType
determing के लिए T
।
template<typename T>
void f(T& param); //param is a reference
int x = 27; // x is an int
const int cx = x; // cx is a const int
const int& rx = x; // rx is a reference to x as a const int
f(x); // T is int, param's type is int&
f(cx); // T is const int, param's type is const int&
f(rx); // T is const int, param's type is const int&
केस 2: ParamType
एक सार्वभौमिक संदर्भ या फॉरवर्ड संदर्भ है। कहीं ऐसा तो नहीं प्रकार कटौती में मामला 1 में रूप में ही है expr
एक rvalue है। यदि expr
एक ParamType
, तो T
और ParamType
दोनों को ParamType
लिए घटाया जाता है।
template<typename T>
void f(T&& param); // param is a universal reference
int x = 27; // x is an int
const int cx = x; // cx is a const int
const int& rx = x; // rx is a reference to x as a const int
f(x); // x is lvalue, so T is int&, param's type is also int&
f(cx); // cx is lvalue, so T is const int&, param's type is also const int&
f(rx); // rx is lvalue, so T is const int&, param's type is also const int&
f(27); // 27 is rvalue, so T is int, param's type is therefore int&&
केस 3: ParamType
न तो पॉइंटर है और न ही रेफरेंस। यदि expr
एक संदर्भ है तो संदर्भ भाग को अनदेखा कर दिया जाता है। अगर expr
है जिसे नजरअंदाज कर दिया जाता है। यदि यह अस्थिर है जिसे टी के प्रकार को कम करने पर भी अनदेखा किया जाता है।
template<typename T>
void f(T param); // param is now passed by value
int x = 27; // x is an int
const int cx = x; // cx is a const int
const int& rx = x; // rx is a reference to x as a const int
f(x); // T's and param's types are both int
f(cx); // T's and param's types are again both int
f(rx); // T's and param's types are still both int
ऑटो प्रकार कटौती
auto
कीवर्ड का उपयोग करके टाइप डिडक्शन टेम्प्लेट टाइप डिडक्शन के समान ही काम करता है। नीचे कुछ उदाहरण दिए गए हैं:
auto x = 27; // (x is neither a pointer nor a reference), x's type is int
const auto cx = x; // (cx is neither a pointer nor a reference), cs's type is const int
const auto& rx = x; // (rx is a non-universal reference), rx's type is a reference to a const int
auto&& uref1 = x; // x is int and lvalue, so uref1's type is int&
auto&& uref2 = cx; // cx is const int and lvalue, so uref2's type is const int &
auto&& uref3 = 27; // 27 is an int and rvalue, so uref3's type is int&&
मतभेद नीचे दिए गए हैं:
auto x1 = 27; // type is int, value is 27
auto x2(27); // type is int, value is 27
auto x3 = { 27 }; // type is std::initializer_list<int>, value is { 27 }
auto x4{ 27 }; // type is std::initializer_list<int>, value is { 27 }
// in some compilers type may be deduced as an int with a
// value of 27. See remarks for more information.
auto x5 = { 1, 2.0 } // error! can't deduce T for std::initializer_list<t>
जैसा कि आप देख सकते हैं कि क्या आप ब्रेडेड इनिशियलाइज़र का उपयोग करते हैं, तो ऑटो को std::initializer_list<T>
का एक वैरिएबल बनाने में मजबूर किया जाता है। यदि यह T
की कटौती नहीं कर सकता है, तो कोड को अस्वीकार कर दिया गया है।
जब auto
को किसी फ़ंक्शन के रिटर्न प्रकार के रूप में उपयोग किया जाता है, तो यह निर्दिष्ट करता है कि फ़ंक्शन का अनुगामी रिटर्न प्रकार है ।
auto f() -> int {
return 42;
}
C ++ 14, C ++ 11 में अनुमत ऑटो के उपयोग के अलावा, निम्नलिखित की अनुमति देता है:
जब अनुगामी रिटर्न प्रकार के बिना फ़ंक्शन के रिटर्न प्रकार के रूप में उपयोग किया जाता है, तो निर्दिष्ट करता है कि फ़ंक्शन के रिटर्न प्रकार को फ़ंक्शन के शरीर में रिटर्न स्टेटमेंट से घटाया जाना चाहिए, यदि कोई हो।
// f returns int: auto f() { return 42; } // g returns void: auto g() { std::cout << "hello, world!\n"; }
जब लैम्बडा के पैरामीटर प्रकार में उपयोग किया जाता है, तो लैम्बडा को एक जेनेरिक लैम्ब्डा के रूप में परिभाषित किया जाता है।
auto triple = [](auto x) { return 3*x; }; const auto x = triple(42); // x is a const int with value 126
विशेष प्रपत्र decltype(auto)
एक प्रकार का decltype
करता है, जो कि auto
बजाय decltype
के टाइप डिडक्शन नियमों का उपयोग करता है।
int* p = new int(42);
auto x = *p; // x has type int
decltype(auto) y = *p; // y is a reference to *p
C ++ 03 और पूर्व में, auto
कीवर्ड का स्टोरेज क्लास स्पेसियर के रूप में पूरी तरह से अलग अर्थ था जो C से विरासत में मिला था।