लैम्बडा क्लोजर लैवेल्यूज़ को रेवल्यू रेफरेंस पैरामीटर के रूप में पास किया जा सकता है


18

मैंने पाया कि lvalueलंबोदर क्लोजर को हमेशा rvalueफंक्शन पैरामीटर्स के रूप में पास किया जा सकता है ।

निम्नलिखित सरल प्रदर्शन देखें।

#include <iostream>
#include <functional>

using namespace std;

void foo(std::function<void()>&& t)
{
}

int main()
{
    // Case 1: passing a `lvalue` closure
    auto fn1 = []{};
    foo(fn1);                          // works

    // Case 2: passing a `lvalue` function object
    std::function<void()> fn2 = []{};
    foo(fn2);                          // compile error

    return 0;
}

केस 2 मानक व्यवहार है (मैंने केवल std::functionप्रदर्शन के उद्देश्यों के लिए उपयोग किया था, लेकिन कोई अन्य प्रकार समान व्यवहार करेगा)।

केस 1 कैसे और क्यों काम करता है? fn1फ़ंक्शन वापस आने के बाद बंद होने की स्थिति क्या है ?


5
मुझे लगता है कि क्योंकि fn1अंतर्निहित रूप से एक std::functionमें रूपांतरित है foo(fn1)। यह अस्थायी कार्य तब एक प्रतिद्वंद्विता है।
ईके

@ रीचर्ड लिखित मैं वास्तव में निश्चित नहीं था, इसलिए मैंने उत्तर नहीं दिया। मुझे लगता है कि अब किसी दूसरे की जरूरत नहीं है।
ईके

1
@ यक एनपी मैं अक्सर एक ही तरह से महसूस करता हूं, और कई उत्तर देता हूं।
रिचर्ड क्रिटिक्स

2
@Sumudu सवाल पूछने वाले ने आपको गुमराह किया क्योंकि वे नहीं जानते थे कि वे क्या पूछना चाह रहे थे। उनके कहने का अर्थ था: " std::functionमेमने से कटौती किए जाने के तर्क क्यों नहीं दिए जा सकते "। आपका प्रोग्राम टेम्पलेट के तर्कों को कम करने का प्रयास नहीं करता है std::function, इसलिए निहित रूपांतरण के साथ कोई समस्या नहीं है।
एरोरिका

1
आपके द्वारा जुड़े प्रश्न का शीर्षक थोड़ा भ्रामक है। std::functionएक गैर-स्पष्ट रचनाकार है जो लंबोदर क्लोजर को स्वीकार करता है, इसलिए इसमें निहित रूपांतरण है। लेकिन जुड़े हुए प्रश्न की परिस्थितियों में, std::functionलैम्बडा प्रकार से टेम्पलेट तात्कालिकता का अनुमान नहीं लगाया जा सकता है। (उदाहरण के लिए std::function<void()>से निर्माण किया जा सकता [](){return 5;}है, भले ही यह एक गैर शून्य वापसी प्रकार है।
इके

जवाबों:


8

केस 1 कैसे और क्यों काम करता है?

आह्वान के fooलिए एक उदाहरण की आवश्यकता होती है, जो std::function<void()>एक संदर्भ संदर्भ को बांधता है । std::function<void()>किसी भी कॉल करने योग्य ऑब्जेक्ट से निर्माण किया जा सकता है जो void()हस्ताक्षर के साथ संगत है ।

सबसे पहले, एक अस्थायी std::function<void()>वस्तु से निर्माण किया जाता है []{}। यहां उपयोग किया गया निर्माणकर्ता # 5 है , जो std::functionउदाहरण में बंद होने की प्रतिलिपि बनाता है :

template< class F >
function( F f );

के साथ लक्ष्य को प्रारंभ करता है std::move(f)। यदि fकोई नल पॉइंटर कार्य करने के लिए या सदस्य को अशक्त सूचक है, *thisतो कॉल के बाद खाली हो जाएगा।

फिर, अस्थायी functionउदाहरण rvalue संदर्भ के लिए बाध्य है।


फ़ंक्शन वापस आने के बाद fn1 बंद होने की स्थिति क्या है?

पहले की तरह ही, क्योंकि यह एक std::functionउदाहरण में कॉपी किया गया था । मूल बंद अप्रभावित है।


8

एक लंबोदर नहीं है std::function। संदर्भ सीधे बाँधता नहीं है

केस 1 काम करता है क्योंकि लंबोदर एस के लिए परिवर्तनीय हैं std::function। इसका मतलब यह है कि एक अस्थायी नकल करकेstd::function भौतिक है । कहा कि अस्थायी एक प्रतिद्वंद्विता संदर्भ के लिए बाध्य होने में सक्षम है, और इसलिए तर्क पैरामीटर से मेल खाता है। fn1

और नकल fn1भी जो कुछ भी होता है उससे पूरी तरह से अप्रभावित है foo


5

फ़ंक्शन वापस आने के बाद fn1 बंद होने की स्थिति क्या है?

fn1 स्टेटलेस है, क्योंकि यह कुछ भी नहीं पकड़ता है।

केस 1 कैसे और क्यों काम करता है?

यह काम करता है क्योंकि तर्क भिन्न प्रकार का है जो संदर्भित संदर्भित है। एक अलग प्रकार होने के कारण, अंतर्निहित रूपांतरण पर विचार किया जाता है। चूंकि लैम्ब्डा इस के तर्कों के लिए कॉल करने योग्य है std::function, इसलिए यह कंवर्टर के कंवर्टर कंस्ट्रक्टर के माध्यम से इसके लिए परिवर्तनीय है std::function। रूपांतरण का परिणाम एक प्रचलन है, और इस प्रकार यह रवैल्यू संदर्भ के साथ बाध्य हो सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.