5

मैं C++ 11 संगामिति (भाग 3) पर एक यूट्यूब वीडियो और निम्नलिखित कोड है, जो संकलित करता है तथा वीडियो में सही परिणाम उत्पन्न करता है भर में आया के दृश्य स्टूडियो कार्यान्वयन।"अर्थ विज्ञान के लिए कदम" और "rvalue संदर्भ"

हालांकि, मुझे विजुअल स्टूडियो 2012 का उपयोग करके इस कोड की संकलन त्रुटि मिली है। संकलक toSin(list<double>&&) के तर्क प्रकार के बारे में शिकायत करता है। यदि मैं तर्क प्रकार को list<double>& पर बदलता हूं, तो कोड संकलित किया गया है।

मेरा प्रश्न move(list) से _tmain() में वापस लौटाया गया है, क्या यह एक रैल्यू संदर्भ है या सिर्फ एक संदर्भ है?

#include "stdafx.h" 
#include <iostream> 
#include <thread> 
#include <chrono> 
#include <list> 
#include <algorithm> 
using namespace std; 

void toSin(list<double>&& list) 
{ 
    //this_thread::sleep_for(chrono::seconds(1)); 
    for_each(list.begin(), list.end(), [](double & x) 
    { 
     x = sin(x); 
    }); 

    for_each(list.begin(), list.end(), [](double & x) 
    { 
     int count = static_cast<int>(10*x+10.5); 
     for (int i=0; i<count; ++i) 
     { 
      cout.put('*'); 
     } 
     cout << endl; 
    }); 
}  

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    list<double> list; 

    const double pi = 3.1415926; 
    const double epsilon = 0.00000001; 
    for (double x = 0.0; x<2*pi+epsilon; x+=pi/16) 
    { 
     list.push_back(x); 
    } 

    thread th(&toSin, /*std::ref(list)*/std::move(list)); 
    th.join();  

    return 0; 
} 
+4

VS2012 बहुत पुराना है, कम से कम VS2013 कोशिश करते हैं और अधिमानतः 2015 –

उत्तर

-1

क्या std::move से दिया जाता है वास्तव में एक rvalue संदर्भ है, लेकिन यह कोई फर्क नहीं पड़ता क्योंकि thread निर्माता अपने तर्कों के लिए एकदम सही अग्रेषण का उपयोग नहीं करता। सबसे पहले यह नए धागे के स्वामित्व वाले भंडारण में प्रतिलिपि/उन्हें स्थानांतरित करता है। फिर, नए धागे के अंदर, आपूर्ति किए गए फ़ंक्शन को प्रतियों का उपयोग करके बुलाया जाता है।

के बाद से प्रतियां अस्थायी ऑब्जेक्ट नहीं है, तो इस चरण rvalue-संदर्भ मानकों करने के लिए बाध्य नहीं होंगे।

स्टैंडर्ड क्या कहते हैं (30.3.1.2):

निष्पादन के नए धागा DECAY_COPY को

INVOKE(DECAY_COPY(std::forward<F>(f)), DECAY_COPY(std::forward<Args>(args))...) 
कॉल के साथ

कार्यान्वित निर्माण सूत्र में मूल्यांकन किया जा रहा।

और

इस खंड आपरेशन DECAY_COPY(x) प्रयोग किया जाता है में कई स्थानों में। ऐसे सभी का उपयोग करता है समारोह decay_copy(x) फोन मतलब है और परिणाम है, जहां decay_copy इस प्रकार परिभाषित किया गया है का उपयोग करें:

template <class T> decay_t<T> decay_copy(T&& v) 
{ return std::forward<T>(v); } 

मूल्य वर्ग खो दिया है।

+0

के लिए सामुदायिक पूर्वावलोकन धागा कॉपी/functors मापदंडों में आंतरिक प्रतियां ले जाने के है? –

+1

यह वीएस2012 कार्यान्वयन में एक बग सही है? –

+0

@MooingDuck: यह क्यों होगा? यह 'std :: thread' के लिए निर्दिष्ट व्यवहार है। –

6

यह MSVC2012 में एक बग प्रतीत होता है। (और त्वरित निरीक्षण पर, MSVC2013 और MSVC2015)

thread सीधे सही अग्रेषण का उपयोग नहीं करता, उद्भव सूत्र में डेटा के लिए एक संदर्भ (अस्थायी या नहीं) भंडारण और पैदा की धागा में इसका उपयोग करने के रूप में अत्यंत त्रुटियों की संभावना हो सकता है और खतरनाक।

इसके बजाय, यह प्रतियां decay_t<?> के आंतरिक डेटा में प्रत्येक तर्क।

बग कि जब यह कार्यकर्ता फ़ंक्शन को कॉल करने, यह सिर्फ है कि आंतरिक प्रति अपनी प्रक्रिया के लिए गुजरता है। इसके बजाय, इसे पर कॉल करना चाहिए जो कॉल में आंतरिक डेटा है।

इस संकलक संस्करण 19 है, जो मुझे लगता है कि MSVC2015 है में लगाई जानी प्रतीत नहीं होता है मानक के शब्द की वजह से अपने कोड संकलन

यहाँ पर यह दोनों है पर आधारित (दोहरी जांच नहीं था), (यह आह्वान करने के लिए माना जाता है एक decay_t<F>decay_t<Ts>... साथ - rvalue, बाध्यकारी बाध्यकारी lvalue नहीं), और स्थानीय डेटा धागा में संगृहीत अपना प्रक्रिया के आह्वान के बाद फिर कभी नहीं इस्तेमाल किया जाएगा क्योंकि (ताकि तार्किक यह समय सीमा समाप्त होना व्यवहार किया जाना चाहिए जिसका मतलब है डेटा, लगातार डेटा नहीं)।

template<class F> 
struct thread_rvalue_fix_wrapper { 
    F f; 
    template<class...Args> 
    auto operator()(Args&...args) 
    -> typename std::result_of<F(Args...)>::type 
    { 
     return std::move(f)(std::move(args)...); 
    } 
}; 
template<class F> 
thread_rvalue_fix_wrapper< typename std::decay<F>::type > 
thread_rvalue_fix(F&& f) { return {std::forward<F>(f)}; } 

तो

thread th(thread_rvalue_fix(&toSin), /*std::ref(list)*/std::move(list)); 

काम करना चाहिए:

यहाँ चारों ओर एक काम है। (ऊपर सूचीबद्ध एमएसवीसी2015 ऑनलाइन कंपाइलर में परीक्षण) व्यक्तिगत अनुभव के आधार पर, इसे MSVC2013 में भी काम करना चाहिए। मुझे MSVC2012 के बारे में पता नहीं है।

+0

चूंकि प्रतिलिपि एक अलग थ्रेड में बनाई गई है, और ** पूर्ण अभिव्यक्ति ** के अंत में नष्ट नहीं हुई है, क्या इसका मतलब यह नहीं है कि प्रतियां प्रचलित नहीं हैं? और ऐसा लगता है कि वे किसी भी मामले में फिट नहीं होते हैं जो उन्हें xvalues ​​बना देगा ... तो फिर वे रैल्यू नहीं हैं और रावल संदर्भों से बंधे नहीं जा सकते हैं। –

+1

@BenVoigt यह एक कार्यान्वयन विस्तार है। मानक आदेश जो 'INVOKE (DECAY_COPY (std :: आगे (एफ)), DECAY_COPY (std :: आगे (तर्क)) ...) बनाए गए धागे द्वारा बुलाया जाएगा। कंपाइलर कुछ भी करने के लिए स्वतंत्र है-अगर ऐसा हुआ। चूंकि 'DECAY_COPY()' का रिटर्न वैल्यू अंतराल से बंधे नहीं जा सकता है, और राजस्व से जुड़ सकता है, एमएसवीसी मानक जनादेश नहीं कर रहा है। सौभाग्य से यह पता लगाना असंभव है कि फ़ंक्शन कॉल के तर्क प्रावधान हैं, इसलिए 'std :: move' संकलक एक्सटेंशन (मुझे लगता है) के बिना आवश्यक परिणाम उत्पन्न करता है। – Yakk

+0

लेकिन INVOKE को पारित पैरामीटर अस्थायी नहीं हैं। तर्कसंगत रूप से मानक को इस मामले को एक्स मान के रूप में कॉल करना चाहिए, लेकिन ऐसा नहीं हुआ है। –

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