2016-09-02 8 views
5

मैं std::forward सीख रहा हूं।क्यों सी ++ तारों को वांछित फ़ंक्शन को कॉल करने के लिए std :: आगे की आवश्यकता नहीं है?

#include <iostream> 
#include <typeinfo> 
#include <string> 
using namespace std; 

class Example { 
}; 

ostream &operator << (ostream &os, const Example &e) { os << "yes!"; return os; } 

void test_forward_inner(const Example &e) { cout << "& " << e << endl; } 
void test_forward_inner(Example &&e) { cout << "&& " << e << endl; } 

void test_forward_inner(const string &e) { cout << "& " << e << endl; } 
void test_forward_inner(string &&e) { cout << "&& " << e << endl; } 

template <typename T> 
void test_forward_wrapper(T &&arg) { 
    test_forward_inner(arg); 
} 

int main() 
{ 
    Example e; 
    test_forward_wrapper(e); 
    test_forward_wrapper(Example()); 

    cout << endl; 

    string s("hello"); 
    test_forward_wrapper(s); 
    test_forward_wrapper("hello"); 

    return 0; 
} 

यहाँ मैं test_forward_wrapper() से test_forward_inner() करने के लिए एक lvalue और एक rvalue अग्रेषित करने के लिए करने की कोशिश की: मैं परीक्षण करने के लिए करता है, तो हम एक और समारोह कॉल करने के लिए तर्क अग्रेषण से पहले std::forward कॉल नहीं करते तो क्या होगा एक छोटी कार्यक्रम में लिखा था। इस कार्यक्रम चल रहा है उत्पादन देता है:

& example 
& example 

& hello 
&& hello 

std::string के लिए है, वांछित भीतरी समारोह बुलाया गया था, लेकिन अपने ही वर्ग के लिए केवल lvalue संस्करण बुलाया गया था। केवल अगर मैं आंतरिक कार्य में तर्क पारित करने से पहले std::forward पर कॉल करता हूं तो रावल्यू संस्करण को कॉल किया जा सकता है।

क्या अंतर यहां है? जैसा कि मुझे पता है, संदर्भ ढहने वाले नियमों के अनुसार, जब रैपर को Example() के साथ बुलाया गया था, तो TExample और arg के रूप में घटाया जाएगा Example && प्रकार इस प्रकार आंतरिक फ़ंक्शन का रावल्यू संस्करण कहा जाना चाहिए।

और, अन्य स्थितियों के लिए std::string मामले के मामले में, आंतरिक फ़ंक्शन का सही संस्करण कहा जाता था, तो क्या हम यहां std::forward हटा सकते हैं? यदि नहीं, तो क्या होगा (शायद कुछ बुरा) होगा?

उत्तर

7

ध्यान दें कि "hello"std::string नहीं है, यह const char[6] है। और test_forward_wrapper() एक फ़ंक्शन टेम्पलेट है, टेम्पलेट तर्क T इसके लिए char const (&)[6] के रूप में घटाया जाएगा।

test_forward_wrapper() अंदर, test_forward_inner()const char[6] है, जो पहली बार में std::string करने के लिए परिवर्तित करने की आवश्यकता के साथ कहा जाता है। यह एक अस्थायी std::string है, यानी एक रावल्यू, जिसे रावल्यू संदर्भ से बाध्य होना पसंद है, यही कारण है कि test_forward_inner(string &&) कहा जाता है।

std::string से test_forward_wrapper() पर एक ही परिणाम प्राप्त होगा।

test_forward_wrapper(std::string("hello")); 
4

अंतर यह है कि

test_forward_wrapper("hello"); 

में "हैलो" यहाँ नहीं एक std::string है। यह const char * है।

बदलें इस एक

test_forward_wrapper(std::string("hello")); 

और परिणाम के लिए कस्टम वर्ग के रूप में एक ही हो जाएगा।

+1

महत्वपूर्ण बात यह है कि आवरण, टेम्प्लेटेड है (ताकि कोई बलात्कार कि कॉल में होता है), जबकि आंतरिक समारोह, नहीं है तो केवल 'स्वीकार करने std :: स्ट्रिंग', जो' स्ट्रिंग' होता है करने के लिए रूपांतरण का मतलब है फिर (आंतरिक कार्य के लिए आर-मूल्य संदर्भ प्रदान करना), कोई अग्रेषण शामिल नहीं है। – ShadowRanger

+3

'" हैलो "' 'कॉन्स चार * नहीं है, यह एक 'कॉन्स्ट चार [6]' है जो' const char * 'में क्षय हो सकता है। । –

+1

^(और इस स्थिति में क्षय नहीं करता है) –

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