C ++ 11 में "ऑटो" के साथ कटौती करने पर लैम्ब्डा का प्रकार क्या है?


142

मुझे यह धारणा थी कि, लंबोदर का प्रकार एक फ़ंक्शन पॉइंटर है। जब मैंने निम्नलिखित परीक्षण किया, तो मैंने इसे गलत ( डेमो ) पाया।

#define LAMBDA [] (int i) -> long { return 0; }
int main ()
{
  long (*pFptr)(int) = LAMBDA;  // ok
  auto pAuto = LAMBDA;  // ok
  assert(typeid(pFptr) == typeid(pAuto));  // assertion fails !
}

क्या उपरोक्त कोड किसी भी बिंदु से गायब है? यदि नहीं, तो कीवर्ड के typeofसाथ कटौती करने पर एक लंबोदर अभिव्यक्ति क्या है auto?


8
"लंबो का प्रकार एक फ़ंक्शन पॉइंटर है" - यह अक्षम होगा और लंबोदर के पूरे बिंदु को याद करेगा।
कोनराड रुडोल्फ

जवाबों:


145

लंबोदर अभिव्यक्ति का प्रकार अनिर्दिष्ट है।

लेकिन वे आमतौर पर फंक्शंस के लिए सिंटैक्टिक शुगर होते हैं। एक मेमने को सीधे एक फनकार में अनुवाद किया जाता है। अंदर कुछ भी []निर्माण पैरामीटर और फंक्शनल ऑब्जेक्ट के सदस्यों में बदल जाता है, और अंदर के पैरामीटर ()फ़ंक्टर के लिए मापदंडों में बदल जाते हैं operator()

एक लैम्ब्डा जो किसी भी चर को पकड़ता है ( []'s के अंदर कुछ भी नहीं ) को एक फ़ंक्शन पॉइंटर में परिवर्तित किया जा सकता है (MSVC2010 इसका समर्थन नहीं करता है, अगर यह आपका कंपाइलर है, लेकिन यह रूपांतरण मानक का हिस्सा है)।

लेकिन लैम्ब्डा का वास्तविक प्रकार एक फ़ंक्शन पॉइंटर नहीं है। यह कुछ अनिर्दिष्ट कवक प्रकार है।


1
MSVC2010 फ़ंक्शन पॉइंटर को रूपांतरण का समर्थन नहीं करता है, लेकिन MSVC11 करता है। blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx
KindDragon

18
"फंक्शंस के लिए मात्र सिंथेटिक चीनी के लिए +1।" इसे याद करके बहुत अधिक संभावित भ्रम से बचा जा सकता है।
बेन

4
एक functor कुछ भी है के साथ operator()मूल रूप से stackoverflow.com/questions/356950/c-functors-and-their-uses
TankorSmash

107

यह एक अद्वितीय अनाम संरचना है जो फ़ंक्शन कॉल ऑपरेटर को अधिभारित करती है। एक लंबोदर का हर उदाहरण एक नए प्रकार का परिचय देता है।

एक गैर-कैप्चरिंग लैम्ब्डा के विशेष मामले में, इसके अलावा संरचना में फ़ंक्शन पॉइंटर का एक अंतर्निहित रूपांतरण है।


2
अच्छा उत्तर। मेरी तुलना में बहुत अधिक सटीक। +1 :)
jalf

4
एकता भाग के लिए +1, यह पहली बार में बहुत ही आश्चर्यचकित करता है और ध्यान आकर्षित करता है।
मैथ्यू एम।

ऐसा नहीं है कि यह वास्तव में मायने रखता है, लेकिन क्या प्रकार वास्तव में अनाम है, या क्या इसे संकलन समय तक केवल नाम नहीं दिया जाता है? IOW, संकलक द्वारा तय किए गए नाम को खोजने के लिए RTTI का उपयोग कर सकता है?
बेन

3
@ नहीं, यह अनाम है और जहां तक ​​C ++ भाषा का संबंध है, "कंपाइलर एक नाम तय करता है" जैसी कोई बात नहीं है। type_info::name()कार्यान्वयन का परिणाम परिभाषित है, इसलिए यह कुछ भी वापस कर सकता है। व्यवहार में, संकलक लिंकर की खातिर प्रकार का नाम देगा।
अवाकर

1
हाल ही में, जब यह सवाल पूछा गया, तो मैं आमतौर पर कहता हूं कि लैम्बडा के प्रकार का एक नाम है, संकलक इसे जानता है, यह सिर्फ अव्यवहारिक है।
आंद्रे कोस्तूर

24

[C++11: 5.1.2/3]: के प्रकार लैम्ब्डा अभिव्यक्ति (जो भी बंद वस्तु के प्रकार है) एक अद्वितीय, अनाम गैर संघ वर्ग प्रकार है - कहा जाता है बंद प्रकार जिसका गुण नीचे वर्णित हैं -। यह वर्ग प्रकार एक समुच्चय (8.5.1) नहीं है। क्लोजर टाइप को सबसे छोटे ब्लॉक स्कोप, क्लास स्कोप या नेम्स्पेस स्पेस में घोषित किया जाता है, जिसमें लैम्बडा-एक्सप्रेशन होता है[..]

इस प्रकार के अलग-अलग गुणों को सूचीबद्ध करने के लिए क्लॉज आगे बढ़ता है। यहाँ कुछ प्रकाश डाला गया है:

[C++11: 5.1.2/5]:लैम्ब्डा-एक्सप्रेशन के लिए क्लोजर प्रकार में एक सार्वजनिक inlineफ़ंक्शन कॉल ऑपरेटर (13.5.4) होता है, जिसके पैरामीटर और रिटर्न प्रकार क्रमशः लैम्ब्डा-एक्सप्रेशन के पैरामीटर-घोषणा-खंड और ट्रेलिंग-रिटर्न-टाइप द्वारा वर्णित किए जाते हैं। [..]

[C++11: 5.1.2/6]:एक के लिए बंद करने के प्रकार लैम्ब्डा अभिव्यक्ति कोई साथ लैम्ब्डा पर कब्जा एक सार्वजनिक गैर आभासी गैर स्पष्ट स्थिरांक रूपांतरण सूचक को कार्य करने के लिए बंद करने के प्रकार के समारोह कॉल ऑपरेटर के रूप में एक ही पैरामीटर और बदले प्रकार होने समारोह है। इस रूपांतरण फ़ंक्शन द्वारा लौटाया गया मान किसी फ़ंक्शन का पता होगा, जिसे लागू करते समय, क्लोजर प्रकार के फ़ंक्शन कॉल ऑपरेटर को लागू करने के समान प्रभाव पड़ता है।

इस अंतिम पारित होने का परिणाम यह है, यदि आप किसी रूपांतरण के लिए इस्तेमाल किया है, तो आप प्रदान करने में सक्षम हो जाएगा है LAMBDAकरने के लिए pFptr


3
#include <iostream>
#include <typeinfo>

#define LAMBDA [] (int i)->long { return 0l; }
int main ()
{
  long (*pFptr)(int) = LAMBDA;  // ok
  auto pAuto = LAMBDA;  // ok

  std::cout<<typeid( *pAuto ).name() << std::endl;
  std::cout<<typeid( *pFptr ).name() << std::endl;

  std::cout<<typeid( pAuto ).name() << std::endl;
  std::cout<<typeid( pFptr ).name() << std::endl;
}

फ़ंक्शन प्रकार वास्तव में समान हैं, लेकिन लैम्ब्डा नए प्रकार (एक फ़न्क्टर की तरह) का परिचय देता है।


यदि आप पहले से ही इस मार्ग पर जा रहे हैं तो मैं CXXABI अनमंगल दृष्टिकोण की सलाह देता हूं । इसके बजाय, मैं आमतौर पर का उपयोग करता हूं __PRETTY_FUNCTION__, जैसे कि template<class T> const char* pretty(T && t) { return __PRETTY_FUNCTION__; }और अगर यह भीड़ लगने लगे तो अतिरिक्त पट्टी उतार दें। मैं टेम्पलेट प्रतिस्थापन में दिखाए गए चरणों को देखना पसंद करता हूं। यदि आप गायब हैं __PRETTY_FUNCTION__, तो MSVC, आदि के लिए विकल्प हैं, लेकिन परिणाम हमेशा एक ही कारण के लिए कंपाइलर-निर्भर होते हैं क्योंकि CXXABI आवश्यक है।
जॉन पी।

1

यह भी ध्यान रखना चाहिए कि लंबोदर फ़ंक्शन पॉइंटर के लिए परिवर्तनीय है। हालाँकि टाइपिड <> एक गैर-त्रैमासिक वस्तु देता है जो लैम्बडा से जेनेरिक फ़ंक्शन पॉइंटर में भिन्न होना चाहिए। तो टाइपिड <> के लिए परीक्षण एक मान्य धारणा नहीं है। सामान्य C ++ 11 में नहीं चाहते हैं कि हम प्रकार विनिर्देश के बारे में चिंता करें, यदि कोई दिया गया प्रकार किसी लक्ष्य प्रकार के लिए परिवर्तनीय है।


यह उचित है, लेकिन मुद्रण प्रकार सही प्रकार के होने की ओर एक लंबा रास्ता तय करता है, उन मामलों को पकड़ने का उल्लेख नहीं करने के लिए जहां प्रकार परिवर्तनीय है, लेकिन अन्य बाधाओं को संतुष्ट नहीं करता है। (मैं जहाँ भी संभव हो, वहाँ हमेशा "अड़चन" को रोकने की ओर धकेलूँगा, लेकिन ऐसा करने की कोशिश करने वाले किसी व्यक्ति के पास विकास के दौरान अपना काम दिखाने का अधिक कारण है।)
जॉन पी।

0

मैं कैसे एक बढ़ावा स्टोर कर सकते हैं से एक व्यावहारिक समाधान :: एक वर्ग के सदस्य के रूप में वस्तु बाँध? , कोशिश करो boost::function<void(int)>या std::function<void(int)>


1
इसके प्रदर्शन की लागत से अवगत रहें, हालाँकि (फ़ंक्शन कहे जाने पर हर बार वर्चुअल फ़ंक्शन कॉल की जाती है)।
हाईकमांडर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.