2013-04-10 10 views
13

सवाल सख्ती से std::function है और boost::function नहीं है। अधिक जानकारी के लिए इस प्रश्न के निचले हिस्से में अनुभाग अपडेट करें, विशेष रूप से इसके बारे में हिस्सा सी ++ 11 मानक के बिना गैर-खाली std::function ऑब्जेक्ट्स की तुलना करना संभव नहीं है।std :: कॉलबैक के रूप में कार्य, अनियंत्रण संभव है?


सी ++ 11 std::function वर्ग टेम्पलेट कॉलबैक का एक संग्रह को बनाए रखने के लिए अच्छा है। कोई उन्हें vector में संग्रहीत कर सकता है, उदाहरण के लिए और आवश्यकता होने पर उन्हें आमंत्रित करें। हालांकि, इन वस्तुओं को बनाए रखना और अपंजीकरण की अनुमति देना असंभव प्रतीत होता है।

इस वर्ग की कल्पना मुझे विशिष्ट होने दो,:

class Invoker 
{ 
public: 
    void Register(std::function<void()> f); 
    void Unregister(std::function<void()> f); 

    void InvokeAll(); 

private: 
    // Some container that holds the function objects passed to Register() 
}; 

नमूना उपयोग परिदृश्य:

void foo() 
{ 
} 

int main() 
{ 
    std::function<void()> f1{foo}; 
    std::function<void()> f2{[] {std::cout << "Hello\n";} }; 

    Invoker inv; 

    // The easy part 

    // Register callbacks 
    inv.Register(f1); 
    inv.Register(f2); 

    // Invoke them 
    inv.InvokeAll(); 

    // The seemingly impossible part. How can Unregister() be implemented to actually 
    // locate the correct object to unregister (i.e., remove from its container)? 
    inv.Unregister(f2); 
    inv.Unregister(f1); 
} 

यह काफी स्पष्ट है कि कैसे Register() समारोह लागू किया जा सकता है। हालांकि, Unregister() को लागू करने के बारे में कोई कैसे जाएगा। आइए मान लें कि फ़ंक्शन ऑब्जेक्ट्स रखने वाला कंटेनर vector<std::function<void()>> है। Unregister() कॉल पर आपको एक विशेष फ़ंक्शन ऑब्जेक्ट कैसे मिलेगा? std::function एक ओवरलोडेड operator== की आपूर्ति करता है, लेकिन यह केवल खाली फ़ंक्शन ऑब्जेक्ट के लिए परीक्षण करता है (यानी, यह दो गैर-खाली फ़ंक्शन ऑब्जेक्ट्स की तुलना करने के लिए उपयोग नहीं किया जा सकता है यह देखने के लिए कि क्या वे दोनों एक ही वास्तविक आमंत्रण) का संदर्भ लेते हैं।

मैं किसी भी विचार की सराहना करता हूं।

अद्यतन:

विचार अब तक मुख्य रूप से एक कुकी के अलावा से मिलकर प्रत्येक std::function उद्देश्य यह है कि यह अपंजीकृत किया जा सकता है के साथ जुड़े होने। मैं ऐसी चीज की उम्मीद कर रहा था जो std::function ऑब्जेक्ट के लिए स्वयं नहीं है। इसके अलावा, std::function और boost::function के बीच बहुत भ्रम प्रतीत होता है। सवाल कड़ाई से std::function ऑब्जेक्ट्स, और boost::function ऑब्जेक्ट्स के बारे में सख्ती से है।

इसके अलावा, आप दो गैर-खाली std::function समानता के लिए वस्तुओं की तुलना नहीं कर सकते हैं। वे हमेशा मानक के बराबर बराबर तुलना करेंगे। इसलिए, उन समाधानों पर टिप्पणियों में लिंक जो केवल ऐसा करते हैं (और बूट करने के लिए boost::function ऑब्जेक्ट्स का उपयोग करें) इस प्रश्न के संदर्भ में गहराई से गलत हैं।

+5

आप एमएस कनेक्शन कनेक्शन के साथ क्या कर सकते हैं: एक कुकी (अपने वेक्टर में इंडेक्स) लौटाएं जो कॉलर अपंजीकरण प्रदान करता है। – WhozCraig

+2

मैं अक्सर इंटरफ़ेस पॉइंटर्स को कॉलबैक के रूप में संग्रहीत करता हूं और उन्हें एक सेट में डालता हूं। फिर मैं अनियंत्रित करने के लिए मूल्य से पहुंच सकता हूं। –

+0

@RogerRowland अच्छा विचार। – WhozCraig

उत्तर

11

चूंकि आप कंटेनर में तत्व पहचान के लिए परीक्षण नहीं कर सकते हैं, इसलिए संभवतः कंटेनर (जैसे std::list) का उपयोग करना सबसे अच्छा है, जिसका कंटेनर संशोधित होने पर इटरेटर्स अमान्य नहीं होता है, और कॉलर को पंजीकृत करने के लिए पुनरावर्तक वापस लौटाता है अपंजीकृत करने के लिए प्रयोग किया जाता है।

यदि आप वास्तव में vector (या deque) का उपयोग करना चाहते हैं, तो कॉलबैक जोड़े जाने पर आप अभिन्न अनुक्रमणिका को वेक्टर/डेक में वापस कर सकते हैं। इस रणनीति को स्वाभाविक रूप से यह सुनिश्चित करने की आवश्यकता होगी कि अनुक्रम में फ़ंक्शन की स्थिति की पहचान करने के लिए इस फैशन में इंडेक्स उपयोग योग्य हैं। यदि कॉलबैक और/या अनियंत्रण दुर्लभ है, तो इसका मतलब यह हो सकता है कि स्पॉट का पुन: उपयोग नहीं किया जा सकता है। या, आप खाली स्लॉट का पुन: उपयोग करने के लिए एक नि: शुल्क सूची लागू कर सकते हैं। या, केवल अनुक्रम के सिरों से रिक्त स्लॉट पुनः प्राप्त करें और बेस इंडेक्स ऑफसेट बनाए रखें जो स्लॉट को शुरुआत से पुनः प्राप्त किए जाने पर बढ़ाया जाता है।

यदि आपके कॉलबैक एक्सेस पैटर्न को यादृच्छिक पहुंच ट्रैवर्सल की आवश्यकता नहीं है, तो std::list में कॉलबैक संग्रहीत करना और अपंजीकृत करने के लिए कच्चे इटरेटर्स का उपयोग करना मेरे लिए सबसे आसान लगता है।

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