2016-08-02 9 views
11

मैं lambdas कि कुछ भी कब्जा नहीं है, हो रही हैकभी नहीं DefaultConstructible

[](){}; 

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

Sidenote:Understanding how Lambda closure type has deleted default constructor एक अलग सवाल पूछ रहा है, हालांकि शीर्षक बहुत समान लगता है। यह पूछ रहा है कि एक स्टेटलेस लैम्ब्डा-ऑब्जेक्ट कैसे उपयोग योग्य डिफॉल्ट कन्स्ट्रक्टर के बिना बनाया गया है। मैं पूछ रहा हूं कि कोई उपयोग करने योग्य डिफ़ॉल्ट कन्स्ट्रक्टर क्यों नहीं है।

+2

[यह प्रश्न] (http: // stackoverflow।कॉम/प्रश्न/32 9 1172 9/समझ-कैसे-लैम्ब्डा-क्लोजर-टाइप-है-डिलीट-डिफॉल्ट-कन्स्ट्रक्टर) प्रासंगिक हो सकता है। –

+0

आप कैसे लैम्ब्डा को डिफॉल्ट-निर्माण करेंगे? '[] {} 'पहले से ही एक बनाता है और आपको उदाहरण देता है। – rustyx

+0

@rustyx ऐसा ही है: 'auto f =() [] {}; f_t = decltype (f) का उपयोग कर; f_t {}; '- यह काम करता है, लेकिन इस तथ्य के लिए कि लैम्बडा ने डिफॉल्ट कन्स्ट्रक्टर को हटा दिया है। –

उत्तर

5

लैम्बडास का उपयोग तब किया जाना है जब इसका उपयोग किया जाए। मानक इस प्रकार कहता है "नहीं, उनके पास डिफ़ॉल्ट कन्स्ट्रक्टर नहीं है"। एक बनाने का एकमात्र तरीका लैम्ब्डा अभिव्यक्ति, या उसकी प्रतियों के माध्यम से है।

वे हैं जो आपके द्वारा चारों ओर रखने और उपयोग करने के लिए विभिन्न प्रकार के लिए लक्षित हैं। ओडीआर उल्लंघनों को इतना जोखिम उठाने के लिए, और ओडीआर उल्लंघनों से बचने के लिए कंपाइलर्स की आवश्यकता होती है, जिससे प्रतीक अत्यधिक जटिल हो जाता है।

हालांकि, C++ 17 आप एक समारोह सूचक के चारों ओर एक राज्यविहीन आवरण लिख सकते हैं:

template<auto fptr> 
struct function_pointer_t { 
    template<class...Args> 
    // or decltype(auto): 
    std::result_of_t< std::decay_t<decltype(fptr)>(Args...) > 
    operator()(Args&&...args)const 
    return fptr(std::forward<Args>(args)...); 
    } 
}; 

और operator void(*)()[](){} पर के रूप में सी ++ 17 में constexpr है, function_pointer_t<+[](){}> एक do-कुछ भी नहीं समारोह वस्तु है वह डिफ़ॉल्ट संरचनात्मक है।

यह वास्तव में लैम्ब्डा को लपेटता नहीं है, बल्कि लैम्ब्डा उत्पादक पॉइंटर-टू-फ़ंक्शन बनाता है।

+1

'function_pointer_t <+[](){}>' '' '' '' '' '' '' '' '' '' '' '' '' 'है –

+3

@ पीटर ए। स्कैनइडर [फ़ैंक पॉइंटर्स पर खाली कैप्चर समूहों के साथ लैम्बडास को परिवर्तित करता है।] (Http://stackoverflow.com/questions/18889028/a-positive-lambda-what-sorcery-is-this) – jaggedSpire

+0

ठीक है, मैंने कोशिश की आपका समाधान लेकिन सी ++ 17 के साथ मैं उपलब्ध था, यह काम नहीं किया। सबसे पहले यह 'टेम्पलेट ' पर ठोकर खा गया, जिसे मैं 'void (*)()' प्रकार का उपयोग करके चारों ओर काम कर सकता था। फिर भी, कंपाइलर्स ने शिकायत की कि 'function_pointer_t <+[](){}>' टेम्पलेट तर्क (जीसीसी) के अंदर लैम्ब्डा अभिव्यक्ति का उपयोग करता है या एक लैम्ब्डा अभिव्यक्ति निरंतर अभिव्यक्ति (क्लैंग) के अंदर प्रकट नहीं हो सकती है। क्या यह सी ++ 17 के संबंध में जीसीसी 6.1 और क्लैंग 3.8 की अपूर्णता के कारण है, या यक का जवाब सी ++ 17 मानक के अनुसार काम नहीं करता है? –

1

मुझे लगता है कि आप प्रकार, वस्तुओं और अभिव्यक्तियों के बीच अंतर से परिचित हैं। सी ++ में, लैम्ब्डा विशेष रूप से लैम्ब्डा अभिव्यक्ति को संदर्भित करता है। गैर-तुच्छ ऑब्जेक्ट को इंगित करने का यह एक सुविधाजनक तरीका है। हालांकि, यह सुविधा है: आप कोड लिखकर स्वयं एक समान वस्तु बना सकते हैं।

अब सी ++ नियमों के अनुसार प्रत्येक अभिव्यक्ति का एक प्रकार होता है, लेकिन उस प्रकार का प्रकार नहीं है जो लैम्ब्डा अभिव्यक्तियों के लिए है। यही कारण है कि यह एक अनाम और अद्वितीय प्रकार है - सी ++ समिति ने उन गुणों को परिभाषित करने के लिए उपयुक्त नहीं माना था। इसी प्रकार, यदि इसे डिफ़ॉल्ट सीटीआर के रूप में परिभाषित किया गया था, मानक को व्यवहार को परिभाषित करना चाहिए। वर्तमान नियम के साथ, डिफ़ॉल्ट ctor के व्यवहार को परिभाषित करने की कोई आवश्यकता नहीं है।

जैसा कि आप ध्यान देते हैं, [](){} के विशेष मामले के लिए यह एक डिफ़ॉल्ट सीटीआर परिभाषित करने के लिए छोटा है। लेकिन उसमें कोई बात नहीं है। आप तुरंत पहले कड़ी प्रश्न पर आते हैं: क्या लैम्ब्डा को डिफ़ॉल्ट सीटीआर परिभाषित किया जाना चाहिए? लैम्ब्डा का क्या सबसेट एक सभ्य परिभाषा के लिए काफी आसान है, फिर भी दिलचस्प होने के लिए पर्याप्त जटिल है? सर्वसम्मति के बिना, आप इसे मानकीकृत होने की उम्मीद नहीं कर सकते हैं।

ध्यान दें कि कंपाइलर विक्रेता, एक एक्सटेंशन के रूप में, पहले से ही यह पेशकश कर सकता है। मानकीकरण अक्सर मौजूदा अभ्यास का पालन करता है, बूस्ट देखें। लेकिन अगर कोई कंपाइलर विक्रेता व्यक्तिगत रूप से इसे सार्थक नहीं सोचता है, तो वे एकजुट क्यों होंगे?

+0

दरअसल, आप एक वस्तु के रूप में लैम्ब्डा के बारे में सोच सकते हैं, जिसे एक निर्माता द्वारा बनाया गया है जो कैप्चर सूची को कन्स्ट्रक्टर तर्क के रूप में लेता है। खाली कैप्चर सूची वाला एक लैम्ब्डा स्वाभाविक रूप से एक डिफ़ॉल्ट कन्स्ट्रक्टर IMHO होना चाहिए। –

संबंधित मुद्दे