2016-12-08 6 views
5

निम्न कोड (on Ideone) मुझे एक त्रुटि क्यों देता है?मैं std :: भविष्य के पैरामीटर में संदर्भ का उपयोग क्यों नहीं कर सकता

#include <future> 
#include <iostream> 
#include <string> 

int main() 
{ 
    int foo = 0; 
    bool bar = false; 
    std::future<std::string> async_request = std::async(
     std::launch::async, 
     [=, &foo](bool& is_pumping_request) -> std::string { 
      return "str"; 
     }, 
     bar 
    ); 
    std::cout << async_request.get() << std::endl; 
} 

आउटपुट:

In file included from /usr/include/c++/5/future:38:0, 
       from prog.cpp:1: 
/usr/include/c++/5/functional: In instantiation of 'struct std::_Bind_simple<main()::<lambda(bool&)>(bool)>': 
/usr/include/c++/5/future:1709:67: required from 'std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...) [with _Fn = main()::<lambda(bool&)>; _Args = {bool&}; typename std::result_of<_Functor(_ArgTypes ...)>::type = std::basic_string<char>]' 
prog.cpp:15:2: required from here 
/usr/include/c++/5/functional:1505:61: error: no type named 'type' in 'class std::result_of<main()::<lambda(bool&)>(bool)>' 
     typedef typename result_of<_Callable(_Args...)>::type result_type; 
                  ^
/usr/include/c++/5/functional:1526:9: error: no type named 'type' in 'class std::result_of<main()::<lambda(bool&)>(bool)>' 
     _M_invoke(_Index_tuple<_Indices...>) 
     ^

हालांकि, अगर मैं पैरामीटर सूची में bool&bool को बदलने के लिए, यह compiles successfully

क्यों?

उत्तर

12

std::thread, std::asyc पैरामीटर को "फ़ंक्शन" के मान से गुजरता है। यदि आप एक समारोह है कि एक संदर्भ लेता है, तो आप समारोह एक const & लेता है तो आप std::cref उपयोग करने की आवश्यकता की तरह

#include <future> 
#include <iostream> 
#include <string> 

int main() 
{ 
    int foo = 0; 
    bool bar = false; 
    std::future<std::string> async_request = std::async(
     std::launch::async, 
     [=, &foo](bool& is_pumping_request) -> std::string { 
      return "str"; 
     }, 
     std::ref(bar) 
    ); 
    std::cout << async_request.get() << std::endl; 
} 

Live Example

चर आप std::ref साथ asyc करने से गुजर रहे हैं रैप करने के लिए की जरूरत है।

+0

'क्रेफ' अच्छा अभ्यास है, लेकिन 'रेफरी' और यहां तक ​​कि कुछ भी नहीं (एक प्रति पास करें) अभी भी काम करेगा (" काम "की कुछ परिभाषा के लिए) –

8

विचार करें कि क्या होगा यदि यह bar संदर्भ से बाध्य करता है।

फिर हर बार जब आप std::async कहते हैं, तो आपके द्वारा पारित हर मूल्य को एसिंक पूरा होने तक ही रहना होगा।

यह आकस्मिक स्मृति भ्रष्टाचार के लिए एक नुस्खा होगा। तो, std::async इसके बदले डिफ़ॉल्ट रूप से प्रतिलिपि बनाते हैं जो आप इसे पास करते हैं।

यह आपके इनपुट की प्रतिलिपि पर कार्य चलाता है।

स्मार्ट होने के नाते, यह उस कोड को बताता है जिसे आप कॉल कर रहे हैं कि यह मान कोड में स्थानांतरित करके गैर-निरंतर है। और lvalue संदर्भ मूल्यों से स्थानांतरित करने के लिए बाध्य नहीं कर सकते हैं।

आप std::reference_wrapper का उपयोग कर इस व्यवहार को ओवरराइड कर सकते हैं। asyncreference_wrapper को समझता है, और यह स्वचालित रूप से उन मानों का संदर्भ संग्रहीत करता है और उन्हें कॉल किए गए कोड के संदर्भ में पास करता है।

reference_wrapper बनाने का आसान तरीका std::ref पर कॉल करना है।

int foo = 0; 
bool bar = false; 
std::future<std::string> async_request = std::async(
    std::launch::async, 
    [=, &foo](bool& is_pumping_request) -> std::string { 
     return "str"; 
    }, 
    std::ref(bar) 
); 
std::cout << async_request.get() << std::endl; 

और यह बस काम करता है।

यह "केवल स्पष्ट रूप से संदर्भ द्वारा पास" ऑपरेशन की तरह बाध्यकारी की एक सुरक्षा सुविधा है; क्योंकि बाध्य निष्पादन वर्तमान स्थिति से आगे बनी रह सकती है, इसके लिए कॉलर्स केवल स्पष्ट रूप से संदर्भ से बंधे होते हैं, इस प्रकार अनजान लटकते संदर्भों का मौका कम करते हैं।

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

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