2015-10-30 14 views
8

में std :: वादा कैप्चर करें मैं एक राज्य मशीन बनाना चाहता हूं जो सबमिट किए गए संकेतों को अपने स्वयं के धागे में संसाधित करता है। मैं विजुअल स्टूडियो 2015 का उपयोग करता हूं, इसलिए सी ++ 11 और आंशिक रूप से सी ++ 14 समर्थित है। सिग्नल कंटेनर में संग्रहीत हैं। प्रत्येक सिग्नल को std :: फ़ंक्शन के रूप में दर्शाया जाता है। मैं क्लाइंट से तब तक इंतजार करना चाहता हूं जब तक राज्य मशीन सबमिट किए गए सिग्नल को संसाधित न करे, इसलिए यह एक प्रकार का सिंक्रोनस सिग्नल है।एक lambda सी ++ 14

मेरी समस्या यह है कि: मैं एक ldda में std :: वादा नहीं कर सकता और इसे कंटेनर में जोड़ सकता हूं।

#include <functional> 
#include <future> 
#include <list> 

std::list<std::function<int()>> callbacks; 

void addToCallbacks(std::function<int()>&& callback) 
{ 
    callbacks.push_back(std::move(callback)); 
} 

int main() 
{ 
    std::promise<int> prom; 
    auto fut = prom.get_future(); 

    // I have made the lambda mutable, so that the promise is not const, so that I can call the set_value 
    auto callback = [proms{ std::move(prom) }]() mutable { proms.set_value(5); return 5; }; 

    // This does not compile 
    addToCallbacks(std::move(callback)); 

    // This does not compile either, however this lambda is a temporal value (lvalue) 
    addToCallbacks([proms{ std::move(prom) }]() mutable { proms.set_value(5); return 5; }); 

    return 0; 
} 

क्या समाधान मैं संदर्भ

  • से वादा पर कब्जा करने से बचना चाहते हैं, तो

    • हैं मैं वादा

    करने के लिए एक * सूचक या एक shared_ptr पर कब्जा करने से बचना चाहते हैं लैम्बडा उत्पन्न करता है किसी भी तरह कक्षा में वादा को एम्बेड करना अच्छा लगेगा। इसका मतलब है कि लैम्ब्डा अब और अधिक गतिशील नहीं है। क्या यह सभी के लिए संभव है?

  • +0

    डिजाइन समीक्षा: 'std :: list' का उपयोग नहीं जब तक आप सच में, सच इटरेटर स्थिरता की आवश्यकता होती है। आपका लक्ष्य "रिटर्न वैल्यू" भविष्य में दिखाना है (जिसे कहीं भी डीकॉप्लेड किया गया है), और उस फ़ंक्शन के रिटर्न वैल्यू में जिसे आप कॉल करते हैं? – Yakk

    उत्तर

    10

    std::function केवल उन मकानों से बनाया जा सकता है जो कॉपी करने योग्य हैं। [Func.wrap.func.con] से:

    template<class F> function(F f); 
    template <class F, class A> function(allocator_arg_t, const A& a, F f); 
    

    आवश्यक है: FCopyConstructible होगा।

    std::promise गैर copyable है, इसलिए वहाँ एक std::function में इस सदस्य के साथ एक functor छड़ी करने के लिए कोई रास्ता नहीं है। अवधि।

    यह देखते हुए कि आप चाहते हैं कि आपका मज़ेदार वास्तव में वादे का स्वामित्व ले ले, यह आपको कई विकल्प नहीं छोड़ता है। बहुत अधिक std::shared_ptr<std::promise>। कोई अन्य विकल्प या तो काम नहीं करता है (उदा। std::unique_ptr<std::promise>), आपको एक खतरनाक वस्तु (उदा। std::reference_wrapper<std::promise>) के साथ छोड़ देता है, या आपको स्मृति-प्रबंधन समस्याओं (उदा। std::promise*) के साथ छोड़ देता है।


    हालांकि, आप std::function के अलावा कुछ और उपयोग कर सकते हैं। आप याक के task विचार here, साथ ही dyp के function_mohere पर एक नज़र डाल सकते हैं, जिनमें से दोनों std::function के चलने योग्य स्वाद बनाते हैं।

    +1

    ओह, डीईपी का 'function_mo' * rude * है - यह 'std :: function' का उपयोग करता है, लेकिन' हैक 'स्टोर करता है जिसमें' एफ' होता है और प्रतिलिपि बनाने का नाटक करता है, लेकिन कहा कि प्रतियां केवल फेंकती हैं (मुझे लगता है कि वे 'std :: terminate' होना चाहिए या अभ्यास में कुछ भी नहीं करना चाहिए, इसलिए वे बता सकते हैं कि वे फेंक नहीं देते हैं)। असल में, यह 'std :: function' पर है, फिर केवल 'std :: function' के हिस्सों को उजागर करता है जो काम करना चाहिए। जब तक आप मानक से गारंटी प्राप्त कर सकते हैं कि कॉपी ऑपरेशन केवल तभी कॉल किया जाएगा जब आप 'std :: function' की प्रतिलिपि बनाते हैं, यह सुरक्षित है, लेकिन इसके लिए कुछ मानक delving की आवश्यकता होगी ... – Yakk

    +0

    आह; यह भी आवश्यक है कि 'एफ' 'एफ()' के रूप में रचनात्मक हो, 'हैक (हैक कॉन्स और)' कॉल 'एफ() 'के रूप में। - tangentally, 'std :: वादा ' 'std :: वादा ' के धारक के रूप में उपयोग किया जा सकता है जो इसके वापसी मूल्य को अनदेखा करता है। या ओपी सिर्फ 'std :: वादा ' (यह सुनिश्चित नहीं कर सकता कि ओपी वापसी मूल्यों के साथ क्या कर रहा है?) – Yakk

    2

    अपने स्वयं के पॉलीमोर्फिक फ़ंक्शन क्लास को रोल करना मुश्किल है। यह उदाहरण तर्क और वापसी प्रकार को हल करता है, लेकिन वांछित होने पर थोड़ा और काम उन्हें टेम्पलेट कर सकता है।

    #include <iostream> 
    #include <functional> 
    #include <future> 
    #include <list> 
    
    // declare a non-polymorphic container for any function object that takes zero args and returns an int 
    // in addition, the contained function need not be copyable 
    class move_only_function 
    { 
        // define the concept of being callable while mutable 
        struct concept 
        { 
         concept() = default; 
         concept(concept&&) = default; 
         concept& operator=(concept&&) = default; 
         concept(const concept&) = delete; 
         concept& operator=(const concept&) = default; 
         virtual ~concept() = default; 
    
         virtual int call() = 0; 
        }; 
    
        // model the concept for any given function object 
        template<class F> 
        struct model : concept 
        { 
         model(F&& f) 
         : _f(std::move(f)) 
         {} 
    
         int call() override 
         { 
          return _f(); 
         } 
    
         F _f; 
        }; 
    
    public: 
        // provide a public interface 
        int operator()() // note: not const 
        { 
         return _ptr->call(); 
        } 
    
        // provide a constructor taking any appropriate object 
        template<class FI> 
        move_only_function(FI&& f) 
        : _ptr(std::make_unique<model<FI>>(std::move(f))) 
        {} 
    
    private: 
        std::unique_ptr<concept> _ptr; 
    }; 
    
    std::list<move_only_function> callbacks; 
    
    void addToCallbacks(move_only_function&& callback) 
    { 
        callbacks.push_back(std::move(callback)); 
    } 
    
    int main() 
    { 
        std::promise<int> prom; 
        auto fut = prom.get_future(); 
    
        // I have made the lambda mutable, so that the promise is not const, so that I can call the set_value 
        auto callback = [proms=std::move(prom)]() mutable { proms.set_value(5); return 5; }; 
    
        // This now compiles 
        addToCallbacks(std::move(callback)); 
    
        std::promise<int> prom2; 
        auto fut2 = prom2.get_future(); 
    
        // this also compiles 
        addToCallbacks([proms = std::move(prom2)]() mutable { proms.set_value(6); return 6; }); 
    
        for (auto& f : callbacks) 
        { 
         std::cout << "call returns " << f() << std::endl; 
        } 
    
        std::cout << "fut = " << fut.get() << std::endl; 
        std::cout << "fut2 = " << fut2.get() << std::endl; 
    
        return 0; 
    } 
    

    उम्मीद उत्पादन:

    call returns 5 
    call returns 6 
    fut = 5 
    fut2 = 6 
    
    +0

    आपने एक पूर्ण समाधान प्रदान किया है। यह अच्छा है। हालांकि मैं कोर सी ++ में अधिक चिपकना चाहता हूं और एक मजेदार के ऐसे विशेष रूपों को पेश नहीं करना चाहता हूं। मुझे लगता है कि मैं वादे को इंगित करने और मूल्य से इसे पकड़ने के लिए एक स्मार्ट सूचक का उपयोग करूंगा। वैसे भी, आपके प्रयासों के लिए धन्यवाद! मैंने आपको इस पोस्ट के लिए +1 दिया है :-) – user2281723