कैसे ठीक से जाँच करें कि क्या std :: फ़ंक्शन C ++ 11 में खाली है?


95

मैं सोच रहा था कि अगर कोई std::functionखाली है तो ठीक से कैसे जांचा जाए। इस उदाहरण पर विचार करें:

class Test {
    std::function<void(int a)> eventFunc;

    void registerEvent(std::function<void(int a)> e) {
        eventFunc = e;
    }

    void doSomething() {
        ...
        eventFunc(42);
    }
};

यह कोड MSVC में बस ठीक-ठाक संकलन करता है, लेकिन अगर मैं कोड doSomething()को शुरू किए बिना कॉल करता हूं तो eventFuncस्पष्ट रूप से क्रैश होता है। यह अपेक्षित है लेकिन मैं सोच रहा था कि इसका क्या मूल्य है eventFunc? डिबगर कहता है 'empty'। इसलिए मैंने तय किया कि यदि कथन का उपयोग सरल है:

   void doSomething() {
        ...
        if (eventFunc) {
            eventFunc(42);
        }
   }

यह काम करता है लेकिन मैं अभी भी सोच रहा हूं कि गैर-आरंभिक मूल्य क्या है std::function? मैं लिखना चाहूंगा if (eventFunc != nullptr)लेकिन std::function(जाहिर है) कोई सूचक नहीं है।

काम करने पर शुद्ध क्यों? इसके पीछे क्या जादू है? और, क्या यह सही तरीका है कि इसे कैसे जांचना है?


8
ध्यान दें कि eventFuncलैम्बडा नहीं है; यह एक है std::function। आप lambdas को std::functions में स्टोर कर सकते हैं , लेकिन वे एक ही चीज़ नहीं हैं।
templatetypedef

3
आप सही हैं, मैंने भ्रम से बचने के लिए शीर्षक बदल दिया। धन्यवाद।
नाइटएफ़ेलिक

जवाबों:


104

आप एक खाली लैम्ब्डा के लिए जाँच नहीं कर रहे हैं, लेकिन क्या std::functionइसमें कॉल करने योग्य लक्ष्य रखा गया है। चेक अच्छी तरह से परिभाषित है और काम करता है std::function::operator boolजिसके कारण boolसंदर्भों में निहित रूपांतरण की अनुमति देता है जहां बूलियन मूल्यों की आवश्यकता होती है (जैसे कि एक ifबयान में सशर्त अभिव्यक्ति )।

इसके अलावा, एक खाली मेमने की धारणा वास्तव में कोई मतलब नहीं है। संकलक के पीछे कंपाइलर एक लैम्ब्डा एक्सप्रेशन को एक struct(या class) परिभाषा में परिवर्तित करता है , जिसके चर आप इस के डेटा सदस्यों के रूप में संग्रहीत पर कब्जा कर लेते हैं struct। एक सार्वजनिक फ़ंक्शन कॉल ऑपरेटर भी परिभाषित किया गया है, जो आपको लैम्ब्डा को लागू करने की अनुमति देता है। तो एक खाली मेमना क्या होगा?


आप if(eventFunc != nullptr)चाहें तो यह भी लिख सकते हैं कि यह उस कोड के बराबर है जो आपके प्रश्न में है। एक के साथ तुलना के लिए std::function परिभाषित करता है operator== और operator!=अधिभार nullptr_t


1
== nullptrहालांकि एक ही काम नहीं करता है ? ऐसा लगता है ==कि ऑपरेटर के लिए एक अधिभार होना चाहिए जो " std::functionतुलना trueकरने के लिए " खाली " का कारण बनता है nullptr: cplusplus.com/reference/functional/function/operators
काइल स्ट्रैंड

3
@KyleStrand हाँ, nullptrकाम करने के लिए तुलना करना भी उपरोक्त प्रश्न के if(eventFunc != nullptr)बराबर है if(eventFunc)
प्रेटोरियन

3
तकनीकी रूप से, std::function::operator boolअंतर्निहित रूपांतरण की अनुमति नहीं देता है bool। यह explicitसब के बाद चिह्नित है , लेकिन मानक कुछ भाषा निर्माणों के लिए एक अपवाद बनाता है जो बूलियन अभिव्यक्तियों की अपेक्षा करते हैं, यह कहते हुए कि "संदर्भ रूप से बूल में परिवर्तित हो गया है।" आप मानक के प्रासंगिक स्निपेट और यहाँ एक स्पष्टीकरण पा सकते हैं: chris-sharpe.blogspot.com/2013/07/…
bcrist

@bcrist Yep, मुझे पता है कि बूलियन रूपांतरण ऑपरेटर है explicit, इसीलिए मैं राज्य के प्रति सावधान था कि संदर्भों में निहित रूपांतरण की अनुमति देता boolहै जहाँ बूलियन मूल्यों की आवश्यकता होती है । यह वास्तव में कोड में क्या हो रहा है।
प्रेटोरियन

5
@Praetorian जिस बिंदु को मैं बनाने की कोशिश कर रहा हूं वह यह है कि मानक "निहित रूपांतरण" वाक्यांश के लिए एक बहुत ही विशिष्ट अर्थ प्रदान करता है, और यह "प्रासंगिक रूपांतरण से बूल" तक अलग है, जिसका एक बहुत विशिष्ट अर्थ भी है। यहाँ कोई "इज़-ए" रिश्ता नहीं है। मैं समझता हूं कि शुरुआती लोगों को अभी निहित / स्पष्ट / प्रासंगिक रूपांतरण के बीच अंतर को जानने की आवश्यकता नहीं है, लेकिन बाद में पुरानी आदतों को तोड़ने के लिए, अवचेतन रूप से सही शब्दों को सीखना बेहतर है।
bcrist

21

यहां देखें http://www.cplusplus.com/reference/functional/function/operator_bool/

उदाहरण

// function::operator bool example
#include <iostream>     // std::cout
#include <functional>   // std::function, std::plus

int main () {
  std::function<int(int,int)> foo,bar;
  foo = std::plus<int>();

  foo.swap(bar);

  std::cout << "foo is " << (foo ? "callable" : "not callable") << ".\n";
  std::cout << "bar is " << (bar ? "callable" : "not callable") << ".\n";

  return 0;
}

उत्पादन

फू को कॉल करने योग्य नहीं है।

बार कॉल करने योग्य है।


31
मुझे लगता है कि यह उत्तर बिना अधिक स्पष्ट होगा swap()। मैं सोच रहा था कि आउटपुट तब तक पीछे था जब तक मुझे एहसास नहीं हुआ।
cp.engr

-1

(मुझे एक स्पष्ट उत्तर प्रदान करते हैं।)

यदि कोई std::functionखाली है तो आप जाँच कर सकते हैं std::function::operator bool

सच: यदि वस्तु कॉल करने योग्य है।
गलत: अन्यथा (ऑब्जेक्ट एक खाली कार्य है)

उदाहरण

#include <iostream>
#include <functional>

int main ()
{
    std::function<int(int,int)> foo = std::plus<int>();//assigned: not empty
    std::function<int(int,int)> bar;//not assigned: empty

    std::cout << "foo is " << (foo ? "not empty" : "empty") << ".\n";
    std::cout << "bar is " << (bar ? "not empty" : "empty") << ".\n";

    return 0;
}

उत्पादन

फू खाली नहीं है।
बार खाली है।


2
आपके परिणाम के तार अदला-बदली किए जाते हैं।
सोफिट

@Sophit क्या आपको यकीन है? ;)
zwcloud

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