2012-06-21 15 views
11

क्यों std :: सी ++ मानक में समारोह <> :: ऑपरेटर() की परिभाषा है:सी ++ 11 std :: समारोह और सही अग्रेषण

R operator()(ArgTypes...) const; 

और नहीं

R operator()(ArgTypes&&...) const; 

?

एक यह है कि लगता होगा सही ढंग से आगे मानकों, हम जरूरत के लिए & & और फिर समारोह शरीर में std::forward<ArgTypes>... का उपयोग कॉल अग्रेषण कब?

मैं आंशिक रूप से std :: समारोह इस परीक्षण करने के लिए reimplemented और मुझे पता चला है कि अगर मैं & & उपयोग करते हैं, मैं "को नहीं बांध सकता 'xxx' lvalue को 'xxx & &'" जी ++ से जब मैं पारित करने के लिए बाद में प्रयास ऑपरेटर के मूल्य के आधार पर पैरामीटर()। मैंने सोचा कि मुझे रावल/अग्रेषण अवधारणाओं की पर्याप्त समझ है, लेकिन फिर भी मैं इस बिंदु को नहीं समझ सकता। मैं क्या खो रहा हूँ?

उत्तर

13

बिल्कुल सही फ़ॉरवर्डिंग केवल तभी काम करती है जब फ़ंक्शन स्वयं (इस मामले में operator()) टेम्पलेट किया गया है और टेम्पलेट तर्क घटाए जाते हैं। std::function के लिए, आपको कक्षा के टेम्पलेट पैरामीटर से तर्क प्रकार प्राप्त होते हैं, जिसका अर्थ है कि उन्हें कभी भी किसी भी तर्क से नहीं लिया जाएगा।

सही अग्रेषण के पीछे पूरी चाल टेम्पलेट तर्क कटौती भाग है, जो संदर्भ ढहने के साथ मिलकर है, यह सही अग्रेषण है।

मैं आसानी से my other answer about std::forward से आसानी से लिंक करूँगा, जहां मैं समझाता हूं कि पूर्ण अग्रेषण (और std::forward) काम करता है।

ध्यान दें कि std::function की operator() को पूर्ण अग्रेषण की आवश्यकता नहीं है, क्योंकि उपयोगकर्ता स्वयं निर्णय लेता है कि पैरामीटर क्या होना चाहिए। यही कारण है कि आप केवल && से operator() नहीं जोड़ सकते हैं; इस उदाहरण को लें:

void foo(int){} 

int main(){ 
    // assume 'std::function' uses 'ArgTypes&&...' in 'operator()' 
    std::function<void(int)> f(foo); 
    // 'f's 'operator()' will be instantiated as 
    // 'void operator()(int&&)' 
    // which will only accept rvalues 
    int i = 5; 
    f(i); // error 
    f(5); // OK, '5' is an rvalue 
} 
+0

धन्यवाद, सब कुछ अब सही समझ में आता है। – airman

+0

@Xeo, आपका कोड सही ढंग से संकलित करता है ... http://ideone.com/7TyCB8 f (i) में कोई त्रुटि नहीं है, क्या आप "// error" से क्या मतलब समझ सकते हैं, या शायद मैं इसका उपयोग कर रहा हूं गलत कंपाइलर धन्यवाद। –

+0

@WillBradley: 'main' के शीर्ष पर टिप्पणी दोबारा पढ़ें: *** मान लीजिए कि' std :: function :: ऑपरेटर() का हस्ताक्षर वास्तव में 'आर (Args && ...)' - यह, 'ऑपरेटर()' के लिए 'v35 (int &&) ''' कार्य करेगा, जो अब केवल रावल स्वीकार करेगा। – Xeo