घोषणापत्र (ऑटो) के कुछ उपयोग क्या हैं?


151

C ++ 14 में decltype(auto)मुहावरा पेश किया गया है।

आमतौर पर इसका उपयोग घोषणाओं को दिए गए अभिव्यक्ति पर नियमों का उपयोग करने की अनुमति देना हैautodecltype

मुहावरे के "अच्छे" उपयोग के उदाहरणों के लिए खोज मैं केवल निम्नलिखित चीजों के बारे में सोच सकता हूं ( स्कॉट मेयर्स द्वारा ), अर्थात् एक फ़ंक्शन की वापसी प्रकार की कटौती के लिए :

template<typename ContainerType, typename IndexType>                // C++14
decltype(auto) grab(ContainerType&& container, IndexType&& index)
{
  authenticateUser();
  return std::forward<ContainerType>(container)[std::forward<IndexType>(index)];
}

क्या कोई अन्य उदाहरण हैं जहां यह नई भाषा सुविधा उपयोगी है?


2
यह पोस्ट मूल रूप से इस मुहावरे से बचने की कोशिश करने का सुझाव देती है क्योंकि इसका उपयोग करते समय आप अपने कंपाइलर stackoverflow.com/a/20092875/2485710 पर
user2485710

मैंने एक बार decltype(auto)कुछ के लिए उपयोग किया था template<class U, V> decltype(auto) first(std::pair<U, V>& p) { return p.first; }, हालांकि मुझे तब एहसास हुआ कि मुझे return (p.first);आश्चर्यजनक रूप से काम करना है (लेकिन IIRC यह भी इरादा है)।
DYP

@ user2485710 यकीन नहीं है कि यह विशेष रूप से अनुकूलन के बारे में है, दुर्घटनाओं के लिए अधिक संभावित अगर decltype(auto)कुछ को कॉपी किया जा सकता है / घोषित ऑब्जेक्ट में ले जाया जा सकता है, तो अपेक्षा के विपरीत।
अंडरस्कोर_ड

जवाबों:


170

जेनेरिक कोड में रिटर्न टाइप फॉरवर्ड करना

गैर-जेनेरिक कोड के लिए, आपके द्वारा दिए गए प्रारंभिक उदाहरण की तरह, आप रिटर्न प्रकार के रूप में संदर्भ प्राप्त करने के लिए मैन्युअल रूप से चयन कर सकते हैं:

auto const& Example(int const& i) 
{ 
    return i; 
}

लेकिन में सामान्य कोड आप के लिए सक्षम होना चाहते हैं पूरी तरह से एक वापसी प्रकार आगे जानने के लिए कि क्या आप एक संदर्भ या एक मूल्य के साथ काम कर रहे बिना। decltype(auto)आपको वह क्षमता प्रदान करता है:

template<class Fun, class... Args>
decltype(auto) Example(Fun fun, Args&&... args) 
{ 
    return fun(std::forward<Args>(args)...); 
}

पुनरावर्ती टेम्प्लेट में वापसी प्रकार की कटौती में देरी

में इस क्यू एंड ए कुछ दिन पहले, टेम्पलेट इन्स्टेन्शियशन दौरान एक अनंत प्रत्यावर्तन जब टेम्पलेट की वापसी प्रकार के रूप में निर्दिष्ट किया गया था का सामना करना पड़ा था decltype(iter(Int<i-1>{}))बजाय decltype(auto)

template<int i> 
struct Int {};

constexpr auto iter(Int<0>) -> Int<0>;

template<int i>
constexpr auto iter(Int<i>) -> decltype(auto) 
{ return iter(Int<i-1>{}); }

int main() { decltype(iter(Int<10>{})) a; }

decltype(auto)टेम्पलेट तात्कालिकता की धूल के निपटारे के बाद वापसी प्रकार की कटौती में देरी के लिए यहां उपयोग किया जाता है ।

अन्य उपयोग

आप decltype(auto)अन्य संदर्भों में भी उपयोग कर सकते हैं , उदाहरण के लिए मानक N3936 का मसौदा भी बताता है

7.1.6.4 ऑटो स्पेक [एर [dcl.spec.auto]

1: autoऔर decltype(auto)टाइप-स्पीशी design र्स एक प्लेसहोल्डर प्रकार को नामित करता है जिसे बाद में बदल दिया जाएगा, या तो एक इनिशलाइज़र से कटौती करके या एक स्पष्ट रिटर्न-प्रकार के साथ स्पष्ट स्पेनी with कटेशन द्वारा। autoटाइप-विशिष्ट एर भी दर्शाता है कि एक लैम्ब्डा एक सामान्य लैम्ब्डा है प्रयोग किया जाता है।

2 प्लेसहोल्डर प्रकार किसी भी संदर्भ में, जहां इस तरह के एक घोषणाकर्ता मान्य है, डिक्लेयर -सीक, टाइप-स्पेसियर-सेक, कनवर्ज़न-फंक्शन-आईडी या ट्रेलिंग-रिटर्न-टाइप में एक फ़ंक्शन घोषणाकर्ता के साथ दिखाई दे सकता है । यदि फ़ंक्शन घोषणाकर्ता में एक ट्रेलिंग-रिटर्न-टाइप (8.3.5) शामिल है, जो फ़ंक्शन के घोषित रिटर्न प्रकार को निर्दिष्ट करता है। यदि फ़ंक्शन के घोषित रिटर्न प्रकार में एक प्लेसहोल्डर प्रकार होता है, तो फ़ंक्शन का रिटर्न प्रकार फ़ंक्शन के शरीर में रिटर्न स्टेटमेंट से कट जाता है, यदि कोई हो।

ड्राफ्ट में वैरिएबल इनिशियलाइज़ेशन का यह उदाहरण भी शामिल है:

int i;
int&& f();
auto x3a = i;                  // decltype(x3a) is int
decltype(auto) x3d = i;        // decltype(x3d) is int
auto x4a = (i);                // decltype(x4a) is int
decltype(auto) x4d = (i);      // decltype(x4d) is int&
auto x5a = f();                // decltype(x5a) is int
decltype(auto) x5d = f();      // decltype(x5d) is int&&
auto x6a = { 1, 2 };           // decltype(x6a) is std::initializer_list<int>
decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression
auto *x7a = &i;                // decltype(x7a) is int*
decltype(auto)*x7d = &i;       // error, declared type is not plain decltype(auto)

17
C ++ 14 में एक नई चीज (i)बनाम का अलग व्यवहार है i?
दानविल

14
@Danvil decltype(expr)और decltype((expr))C ++ 11 में पहले से ही अलग हैं, यह उस व्यवहार को सामान्य करता है।
टेम्पलेटरेक्स

13
मैंने अभी यह सीखा है, एक भयानक डिजाइन निर्णय की तरह लगता है ... कोष्ठक के वाक्यविन्यास अर्थ में समय की पाबंदी को जोड़ना।
काहलर

हमेशा इस घृणा का संकेत देने वाला उदाहरण वन-लाइनर फ़ाइल-टू-स्ट्रिंग सिंटैक्स (उस लिंक में भी उल्लिखित) है। इसका हर हिस्सा पिछड़ा हुआ लगता है। आप अस्पष्टता की बिल्कुल भी उम्मीद नहीं कर सकते हैं, और अनिवार्य रूप से एक नमूना से अनावश्यक कोष्ठक हटा सकते हैं; आप SFINAE के अनुसार निष्कासन की प्रक्रिया से हल करने के लिए अस्पष्टता उम्मीद होती है, लेकिन घोषणा के अलावा अन्य उम्मीदवारों अग्रिम (एस एफ में समाप्त हो जाते भावी है एई); और हताशा में आप जैसे ही आगे बढ़ सकते हैं, यह सोचता है कि मनमाने पारेंस अस्पष्टता को हल करते हैं, लेकिन वे इसका परिचय देते हैं। CS101 प्राध्यापकों के लिए मैं सबसे ज्यादा घबराता हूं।
जॉन पी

@TemplateRex: संदर्भित प्रश्न में रिटर्न प्रकार के रिज़ॉल्यूशन में देरी के बारे में: जहाँ तक मैं देख रहा हूँ, विशिष्ट परिदृश्य में , एक साधारण autoने ठीक वैसे ही काम किया होगा, जैसा कि परिणाम वैसे भी मूल्य द्वारा वापस किया जाता है ... या मुझे याद नहीं किया कुछ कुछ?
एकांकागुआ

36

सामान यहाँ से उद्धृत करना :

  • decltype(auto)प्राथमिक रूप से फ़ॉरवर्डिंग फ़ंक्शंस और इसी तरह के रैपर को समर्पित करने के लिए मुख्य रूप से उपयोगी है , जहाँ आप चाहते हैं कि टाइप "ट्रैक" कुछ अभिव्यक्ति को आमंत्रित कर रहे हैं।

  • उदाहरण के लिए, नीचे दिए गए कार्य:


   string  lookup1();
   string& lookup2();

  • C ++ 11 में हम निम्नलिखित रैपर फ़ंक्शन लिख सकते हैं जो रिटर्न प्रकार के संदर्भ-नेस को संरक्षित करना याद रखते हैं:

   string  look_up_a_string_1() { return lookup1(); }
   string& look_up_a_string_2() { return lookup2(); }

  • C ++ 14 में, हम इसे स्वचालित कर सकते हैं:

   decltype(auto) look_up_a_string_1() { return lookup1(); }
   decltype(auto) look_up_a_string_2() { return lookup2(); }

  • हालाँकि, इससे decltype(auto)परे एक व्यापक रूप से इस्तेमाल की जाने वाली विशेषता नहीं है।

  • विशेष रूप से, हालांकि इसका उपयोग स्थानीय चर घोषित करने के लिए किया जा सकता है , ऐसा करना शायद एक एंटीपैटर्न है क्योंकि स्थानीय चर के संदर्भ-नेस को आरंभीकरण अभिव्यक्ति पर निर्भर नहीं होना चाहिए।

  • इसके अलावा, यह संवेदनशील है कि आप रिटर्न स्टेटमेंट कैसे लिखते हैं।

  • उदाहरण के लिए, नीचे दिए गए दो कार्यों के अलग-अलग प्रकार हैं:


   decltype(auto) look_up_a_string_1() { auto str = lookup1(); return str; }
   decltype(auto) look_up_a_string_2() { auto str = lookup2(); return(str); }

  • पहला रिटर्न string, दूसरा रिटर्न string&, जो स्थानीय चर का संदर्भ है str

से प्रस्ताव आप अधिक इरादा उपयोग करता है देख सकते हैं।


3
सिर्फ autoरिटर्न के लिए क्यों नहीं इस्तेमाल किया जाता?
B:08овиЈ

@ B typeовиЈ सामान्यीकृत रिटर्न प्रकार कटौती (यानी, autoवापसी) के साथ भी काम कर सकता था, लेकिन ओपी ने विशेष रूप से उपयोग के लिए कहा decltype(auto)
19010 में 101010

3
यह सवाल हालांकि अभी भी प्रासंगिक है। वापसी का प्रकार क्या होगा auto lookup_a_string() { ... } ? क्या यह हमेशा एक गैर-संदर्भ प्रकार है? और इसलिए auto lookup_a_string() ->decltype(auto) { ... }संदर्भों को (कुछ मामलों में) वापस करने की अनुमति देने के लिए मजबूर करने की आवश्यकता है?
हारून मैकडैड

@AaronMcDaid Deductible autoको मान टेम्पलेट द्वारा पास की अवधि में परिभाषित किया गया है, इसलिए हाँ यह एक संदर्भ नहीं हो सकता है। कृपया- autoसंदर्भ, संदर्भ सहित कुछ भी हो सकता है।
जिज्ञासु

4
उल्लेख के लायक एक अतिरिक्त उदाहरण एक तत्व वापस कर रहा है std::vector। बोलो तुम्हारे पास है template<typename T> struct S { auto & operator[](std::size_t i) { return v[i]; } std::vector<T> v; }। की वजह से फिर S<bool>::operator[]एक झूलते हुए संदर्भ वापस आ जाएंगे std::vector<bool>decltype(auto)इस समस्या को दरकिनार करने के लिए रिटर्न प्रकार बदलना ।
Xoph
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.