2014-09-24 10 views
27

इस सी ++ 11 कोड पर विचार करें:क्या सी ++ 11 को इस लैम्ब्डा को म्यूटेबल घोषित करने की आवश्यकता है?

#include <functional> 
#include <cstdlib> 

template <typename F> 
void test(F &&f) { 
    auto foo = [f]() { 
     f(); 
    }; 
    foo(); 
} 

int main() { 
    test(std::bind(std::puts, "hello")); 
    return 0; 
} 

जीसीसी और बजना इस रूप में मान्य सी ++ 11 कोड स्वीकार करते हैं, लेकिन विजुअल स्टूडियो 2013 परिवर्तनशील घोषित करने की आवश्यकता है लैम्ब्डा (auto foo = [f]() mutable { ... })। अन्यथा मैं इस त्रुटि मिलती है:

error C3848: expression having type ' const std::_Bind<true,int,int (__cdecl *const)(const char *),const char (&)[6]> ' would lose some const-volatile qualifiers in order to call ' int std::_Bind<true,int,int (__cdecl *const)(const char *),const char (&)[6]>::operator()<>(void) '

दृश्य स्टूडियो परिवर्तनशील बिना इस कोड को अस्वीकार करने का अधिकार है, या यह मान्य सी ++ 11 है?

उत्तर

14

यह lambdas के बारे में वास्तव में नहीं है,

(। मैं काफी यकीन है कि यह एक बग है कर रहा हूँ अगर आप बदलना std::bind(std::puts, "hello") जाहिरा तौर पर, क्योंकि यह मानता है noreturn समारोह प्रकार अलग बनाने के लिए std::bind(std::exit, 0) को मजे की बात है बजना कोड को खारिज कर दिया) ।

#include <functional> 
#include <cstdlib> 

int main() { 
    const auto x = std::bind(std::puts, "hello"); 
    x(); 
} 

यह जीसीसी द्वारा स्वीकार किया जाता है, लेकिन एमएसवीसी द्वारा खारिज कर दिया जाता है।

मानक यह स्पष्ट नहीं है कि यह मान्य है, आईएमओ। के वापसी मूल्य g में एक अनिर्दिष्ट रिटर्न प्रकार है जिसके लिए g(...)g के सीवी-क्वालीफायर के संदर्भ में मान्य और परिभाषित है, लेकिन मानक वास्तव में यह नहीं कहता कि operator()const-योग्य वस्तुओं या संदर्भों के लिए कॉल करने योग्य होना चाहिए। यह दृढ़ता से तात्पर्य है कि यह वैध होना है, क्योंकि अन्यथा g के सीवी-क्वालीफायर का संदर्भ बेकार लगता है, लेकिन यह वास्तव में यह नहीं कहता कि यह मान्य है।

इसके कारण, मुझे लगता है कि एमएसवीसी का व्यवहार मानक लेखकों के इरादे से नहीं है, लेकिन फिर भी यह मानक की आवश्यकता के अनुरूप हो सकता है।

+0

नहीं, यह मानक के अनुरूप नहीं है। "जी (यू 1, यू 2, ..., यूएम) का प्रभाव' INVOKE (एफडी, v1, v2, ..., vN, result_of <एफडी सीवी (वी 1, वी 2, ..., वीएन 'होगा)> :: प्रकार) '" का अर्थ है कि बाध्य कार्य ऑब्जेक्ट है, तो 'बाइंड' का परिणाम कॉल करने योग्य होना चाहिए। फ़ंक्शन पॉइंटर कॉल करने योग्य है या नहीं, यह 'const' है, इसलिए 'बाइंड' चीज़ भी होनी चाहिए। –

+0

@ माइकसेमोर 'जी'' std :: bind' का वापसी मान है, और केवल 'g (...)' ™ व्यवहार निर्दिष्ट है। मानक को उस वापसी मूल्य के 'कॉन्स्ट'-योग्य संदर्भ के माध्यम से कॉल का समर्थन करने की आवश्यकता होती है? – hvd

+0

मैंने उद्धरण में (20.8.9.1.2/3), साथ ही निम्नलिखित खंड "जहां' सीवी' 'जी' के सीवी-क्वालीफायर का प्रतिनिधित्व करता है। 'जी' को कॉल करना 'एफडी'' के लिए लागू 'जी' के सीवी-क्वालिफायर के साथ 'एफडी' (बाध्य कार्य ऑब्जेक्ट) का आह्वान करने जैसा ही प्रभाव पड़ता है; इसलिए 'const 'की योग्य प्रतिलिपि /' g' के संदर्भ को कॉल मान्य होना चाहिए यदि 'कॉन्स एफडी' का आविष्कार है। यहां, 'एफडी' एक फ़ंक्शन पॉइंटर प्रकार है, जो कॉल करने योग्य है या नहीं, यह 'const' है। –

10

यह bind के विजुअल स्टूडियो कार्यान्वयन में एक बग जैसा दिखता है, केवल एक गैर-कॉन्स्ट फ़ंक्शन कॉल ऑपरेटर के साथ एक प्रकार लौटाता है। इसे एक प्रकार वापस करना चाहिए जो कि सभी फ़ंक्शन बाध्य फ़ंक्शन ऑब्जेक्ट को कॉल करता है, भले ही इसकी अपनी सीवी-योग्यताएं हों।

सी ++ 11 20.8.9.1.2 की बजाय अपारदर्शी भाषा को सारांशित करने के लिए, bind के परिणाम पर फ़ंक्शन कॉल बाध्य फ़ंक्शन ऑब्जेक्ट पर अग्रेषित किए जाने चाहिए, और इसलिए उस ऑब्जेक्ट पर कॉल की अनुमति दी जानी चाहिए । इसलिए यदि const पर बाध्य फ़ंक्शन ऑब्जेक्ट कॉल करने योग्य नहीं है तो यह एक त्रुटि होगी; लेकिन यहां, एक फंक्शन पॉइंटर होने के नाते, यह सीवी-योग्यता के बावजूद कॉल करने योग्य है।

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