2013-03-02 6 views
7

सी ++ 11 उपलब्ध नहीं होने पर std::function<> के लिए सरोगेट के रूप में किस निर्माण का उपयोग किया जाना चाहिए?
वैकल्पिक रूप से नीचे एक उदाहरण के रूप में एक वर्ग के निजी सदस्य कार्यों तक पहुंचने की अनुमति देनी चाहिए जैसे कि नीचे दिए गए उदाहरण (std :: function की अन्य विशेषताओं का उपयोग नहीं किया जाता है)। कक्षा फू तय है और ज्यादा नहीं बदला जा सकता है, मेरे पास केवल कक्षा बार तक पहुंच है।क्या सी ++ 11 से पहले std :: function के समान कुछ है?

class Foo { 
    friend class Bar; // added by me, rest of the class is fixed 
    private: 

    void doStuffFooA(int i); 
    void doStuffFooB(int i); 
}; 

class Bar { 
    public: 

    Bar(Foo foo, std::function< void (const Foo&, int) > func) { 
    myFoo = foo; 
    myFooFunc = func; 
    }; 

    private: 

    doStuffBar(const &Foo foo) { 
    myFooFunc(foo, 3); 
    } 

    Foo myFoo; 
    std::function< void (const Foo&, int) > myFooFunc; 
} 

int main() { 

    Foo foo(...); 

    Bar barA(foo, &Foo::doStuffFooA); 

    Bar barB(foo, &Foo::doStuffFooB); 
    ... 
} 
+1

इस कोड को संकलित नहीं किया जाना चाहिए, भले ही स्पष्ट वाक्यविन्यास त्रुटियों को ठीक कर रहे हैं। दो 'बार' ऑब्जेक्ट्स को व्यक्तिगत सदस्य कार्यों के लिए पॉइंटर्स के साथ बनाया गया है, लेकिन जहां यह होता है, उस कोड के पास उन सदस्यों तक पहुंच नहीं है। इसका 'std :: function' से कोई लेना देना नहीं है; यह एक्सेस नियमों को तोड़ने के लिए नहीं मिलता है। –

उत्तर

10

वहाँ से पहले सी ++ 11 :: समारोह एसटीडी कुछ इसी तरह है?

हाँ। Boost.Function (boost::function<>) है, जो हाल ही में सी ++ मानक लाइब्रेरी का हिस्सा बन गया है और std::function<> के लिए संदर्भ कार्यान्वयन प्रदान किया गया है; इसी प्रकार, Boost.Bind (boost::bind<>()) मानक द्वारा अपनाया गया था और std::bind<>() बन गया।

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

#include <memory> 

template<typename T> 
struct fxn { }; 

template<typename R, typename... Args> 
struct fxn<R(Args...)> 
{ 

public: 

    template<typename F> 
    fxn(F&& f) 
     : 
     _holder(new holder<typename std::decay<F>::type>(std::forward<F>(f))) 
    { } 

    R operator() (Args&&... args) 
    { _holder->call(std::forward<Args>(args)...); } 

private: 

    struct holder_base 
    { virtual R call(Args&&... args) = 0; }; 

    template<typename F> 
    struct holder : holder_base 
    { 
     holder(F&& f) : _f(std::forward<F>(f)) { } 
     R call(Args&&... args) { return _f(std::forward<Args>(args)...); } 
     F _f; 
    }; 

    std::unique_ptr<holder_base> _holder; 
}; 

#include <iostream> 

int main() 
{ 
    fxn<void()> f = [] { std::cout << "hello"; }; 
    f(); 
} 
+0

दरअसल, बूस्ट से कई सुविधाएं "प्री-स्टैंडर्ड" के रूप में देखी जा सकती हैं। – leemes

+0

अच्छा कोड जो दिखाता है कि हम इसे स्क्रैच से कैसे बना सकते हैं, लेकिन आपको यह ध्यान रखना होगा कि यह सी ++ 11 है। ;) मुझे लगता है कि बढ़ावा कार्यान्वयन कहीं अधिक जटिल है (मुझे लगता है कि वे इसके लिए अपनी प्रीप्रोसेसर लाइब्रेरी का उपयोग करते हैं?) – leemes

+0

@leemes: हां, ज़ाहिर है। मैं बस कार्यान्वयन सिद्धांत, कम या ज्यादा क्या पर एक अंतर्दृष्टि प्रदान करना चाहता था। यह केवल सी ++ 11 नहीं है, बल्कि यह भी बहुत ही रूढ़िवादी है। –

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