2011-11-10 28 views
11
int func(int x){return x;} 
... 
std::function<int(int)> x = std::bind(func, std::placeholders::_1); 
x(123); 
  1. x(123) वास्तव में functor जो std::function उत्पन्न जो बारी में functor जो std::bind उत्पन्न जो अंत में func कॉल की operator() कॉल की operator() फोन करता है? क्या यह func(123) पर कॉल करने के रूप में इष्टतम के रूप में कुछ अनुकूलित किया गया है?
  2. फ़ैक्टर कहाँ रहता है std::bind उत्पन्न करता है? किस दायरे में? और std::bind नाम कैसे है? (नाम टकराव हो सकते हैं)
  3. क्या लैम्बडा std::bind के सभी उपयोगों को प्रतिस्थापित कर सकता है?
  4. std::bind है इसके बजाय इसे लैम्ब्डा के रूप में कार्यान्वित करने के रूप में इष्टतम के रूप में?
  5. std::function के टेम्पलेट तर्क के वाक्यविन्यास के साथ क्या हो रहा है? यह पार्स कैसे प्राप्त करता है और मैं उस टेम्पलेट तर्क वाक्यविन्यास को कहीं और कैसे उपयोग कर सकता हूं?
+2

2. आप में रुचि हो सकती है http://www.artima.com/cppsource/type_erasure.html – Flexo

+4

एक समय में एक प्रश्न, कृपया। प्रत्येक एसओ पोस्ट एक सवाल है। –

+0

यह एक ठोस प्रश्न की तुलना में प्रश्नों का एक सेट है, और वे वाक्यविन्यास ('फ़ंक्शन <> 'के तर्क के लिए) के व्यवहार से हैं (बाध्य रहते हैं? क्या लैम्ब्डा उन्हें प्रतिस्थापित कर सकता है?) प्रदर्शन (इच्छा इसे अनुकूलित किया जा सकता है?) –

उत्तर

16

करता है एक्स (123) वास्तव में functor के ऑपरेटर() फोन जो std :: फ़ंक्शन जेनरेट करता है जो बदले में मज़ेदार के ऑपरेटर() को कॉल करता है जो std :: bind उत्पन्न होता है जो आखिरकार func को कॉल करता है? क्या यह func (123) को कॉल करने के रूप में इष्टतम के रूप में कुछ अनुकूलित किया गया है?

मैं std::function 'के रूप में उत्पन्न' (यह एक नियमित सदस्य है) की operator() का वर्णन नहीं होगा, लेकिन अन्यथा यह एक अच्छा वर्णन है। अनुकूलन आपके कंपाइलर पर निर्भर हैं, लेकिन चेतावनी दीजिये कि std::function (जिसे टाइप एरर के उपयोग की आवश्यकता होती है) के संकेत को अनुकूलित करने के लिए एक कंपाइलर को नायकों को करने की आवश्यकता हो सकती है।

फ़ैक्टर जीवित कहां रहता है जो std :: bind उत्पन्न करता है? किस दायरे में? और std :: बाइंड का नाम कैसे है? (वहाँ नाम टकराव हो सकता है)

std::bind करने के लिए कॉल अनिर्दिष्ट प्रकार के एक functor देता है, और कहा कि functor की एक प्रति x ऑब्जेक्ट के अंदर संग्रहित है। यह प्रतिलिपि x तक ही रहेगी। इसमें कोई नाम शामिल नहीं है इसलिए मुझे यकीन नहीं है कि इसका मतलब क्या है।

क्या lambdas std :: bind के सभी उपयोगों को प्रतिस्थापित कर सकता है?

संख्या पर विचार करें auto bound = std::bind(functor, _1); जहां functor एक ओवरलोड operator() साथ एक प्रकार है, के long और int पर मान लीजिए। फिर bound(0L) का bound(0) जैसा ही प्रभाव नहीं है और आप इसे लैम्ब्डा से दोहराना नहीं कर सकते हैं।

std :: बजाय एक लैम्ब्डा के रूप में यह लागू करने के रूप में इष्टतम के रूप में बाँध है?

यह कंपाइलर पर निर्भर है। खुद को मापो।

std :: function के टेम्पलेट तर्क के वाक्यविन्यास के साथ क्या हो रहा है? यह पार्स कैसे प्राप्त करता है और मैं उस टेम्पलेट तर्क वाक्यविन्यास को कहीं और कैसे उपयोग कर सकता हूं?

यह एक फ़ंक्शन प्रकार है। शायद आप फंक्शंस के लिए पॉइंटर्स/संदर्भों के लिए वाक्यविन्यास से पहले ही परिचित हैं: void(*)(), int(&)(double)। फिर बस प्रकार के पॉइंटर/संदर्भ को हटा दें, और आपके पास अभी एक फ़ंक्शन प्रकार है: void(), int(double)

typedef int* function_type(long); 
function_type* p; // pointer to function 
+2

+1 का प्रश्न केवल प्रश्न के सही जवाब के लिए 0 #: एक मज़ेदार है एक वस्तु, कोई जादुई वर्ग पीढ़ी शामिल नहीं है। –

+1

स्थिर पॉलीमोर्फिज्म (बाइंड) बनाम मोनोमोर्फिक प्रोटोटाइप (फ़ंक्शन <>) पहली बार दौर में अंतर आया :) वास्तव में काफी गहरा लेकिन आसानी से अनदेखा अंतर। (आपके पास शुरुआत से मेरा +1 था) – sehe

+0

+1 'बाइंड' के उपयोग के मामले में जिसे लैम्ब्डा के साथ दोहराया नहीं जा सकता है। –

6

1। क्या x(123) वास्तव में operator() को मज़दूर के operator() पर कॉल करता है जो std::function उत्पन्न करता है जो बदले में operator() फ़ंक्शन के operator() को कॉल करता है जो अंततः func पर कॉल करता है? क्या यह func(123) पर कॉल करने के रूप में इष्टतम के रूप में कुछ अनुकूलित किया गया है?

आप अनुकूलन सक्षम हैं, 'सामान' inlined हो जाता है और आप इस func(123) बुला के रूप में के रूप में किया जा रहा है इष्टतम पर भरोसा कर सकते हैं।

2। मज़ेदार कहां रहता है std::bind उत्पन्न करता है? किस दायरे में? और std::bind नाम कैसे है? (वहाँ नाम टकराव हो सकता है)

Precising: bind एक 'क्षणभंगुर', कार्यान्वयन परिभाषित उत्पन्न करता है, अभिव्यक्ति के लिए बाध्य, कि function<> को आबंटित है। समारोह सिर्फ एक वर्ग टेम्पलेट है (धन्यवाद, ल्यूक टी।)। और यह मानक पुस्तकालय में रहता है। हालांकि, बाध्य अभिव्यक्ति कार्यान्वयन परिभाषित हैं।

मानक लाइब्रेरी ऐसे अभिव्यक्तियों के एमपीएल पहचान को अनुमति देने के लिए लक्षणों (std::is_bind_expression<>) के साथ आते हैं। Std :: function पर बाइंड एक्सप्रेशन की एक निर्णायक विशेषता यह है कि वे हैं (मैं क्या कहूंगा) स्थगित कॉल करने योग्य ऑब्जेक्ट्स (यानी वे वास्तविक कॉल साइट पर अधिभार चुनने की क्षमता सहित पूर्ण कॉल साइट अर्थशास्त्र बनाए रखते हैं)। std::function<>, दूसरी तरफ, एक प्रोटोटाइप में आता है और आंतरिक रूप से callable object को टाइप एरर (सोच variant या any) द्वारा आंतरिक रूप से स्टोर करता है।

3। क्या lambdas std :: bind के सभी उपयोगों को प्रतिस्थापित कर सकता है?

4। क्या std :: इसके बजाय लैम्ब्डा के रूप में इसे लागू करने के रूप में इष्टतम के रूप में बांधता है?

AFAICT lambdas को बाइंड अभिव्यक्तियों के समान ही संकलित करना चाहिए। एक बात है कि मुझे लगता है कि lambdas कि बाँध भाव नहीं कर सकते कर सकते हैंnested bind expressions है संपादित नेस्टेड बाँध भाव के विशिष्ट मुहावरा lambdas का उपयोग कर replicatable नहीं है, lambdas के पाठ्यक्रम को व्यक्त करने में सक्षम हैं (लगभग) एक ही और अधिक स्वाभाविक रूप से:

bind(f, bind(g, _1))(x); 
// vs. 
[](int x) { f(g(x)); }; 

 

5।std::function के टेम्पलेट तर्क के सिंटैक्स के साथ क्या हो रहा है? यह पार्स कैसे प्राप्त करता है और मैं उस टेम्पलेट तर्क वाक्यविन्यास को कहीं और कैसे उपयोग कर सकता हूं?

यह सिर्फ एक समारोह हस्ताक्षर (एक समारोह के प्रकार), टेम्पलेट पैरामीटर के रूप में पारित किया जा रहा है।

आप इसे फ़ंक्शन पैरामीटर प्रकार के रूप में भी उपयोग कर सकते हैं, जो फ़ंक्शन पॉइंटर में घटता है (जैसा कि सरणी द्वारा-मूल्य पैरामीटर पॉइंटर्स को डाउनग्रेड करते हैं, धन्यवाद डेविड!)। अभ्यास में, सबसे कहीं भी, जब तक कि आप नाम एक चर/प्रकार की जरूरत नहीं है:

void receiveFunction(void(int, double)); // spunky 'function<>'-style syntax 

void sample(int, double) { } 

int main() 
{ 
    receiveFunction(sample); 
} 

void receiveFunction(void (*f)(int, double)) // boring 'old' style syntax 
//     void (f)(int, double) // ... also ok 
{ 
    // .. 
} 
+0

मानते हैं कि 'एफ' और' जी 'अधिभारित नहीं हैं, फिर नेस्टेड बाइंड अभिव्यक्ति को लैम्ब्डा के रूप में व्यक्त किया जा सकता है: '[] (टी टी) {वापसी एफ (जी (टी)); } '। –

+0

@LucDanton: आपके उत्तर में जानकारी मिली। उस – sehe

+1

के लिए +1 मैं बिंदु 2 पर असहमत हूं: सही उत्तर यह है कि 'बाइंड' द्वारा "जेनरेट" कोई फिक्स्चर नहीं है, केवल एक अस्थायी ऑब्जेक्ट फ़ंक्शन द्वारा लौटाया गया है, जिसका कोई नाम नहीं है और अभिव्यक्ति के समय के लिए लाइव होगा यह प्रतीत होता है (सभी अस्थायी की तरह)। यह अस्थायी 'x' आरंभ करने के लिए प्रयोग किया जाता है। –

0

lambdas एसटीडी के सभी उपयोगों की जगह ले सकता :: bind: तुम कितने तरह उन का उपयोग कर सकते हैं?

सी ++ 14 लैम्बडा को ज्यादातर बांधने की अनुमति देगा। विशेष रूप से ल्यूक डैंटन के जवाब में प्रतिक्रिया देते हुए, सी ++ 14 में, आप ऑटो का उपयोग करके टेम्पलेटेड लैम्ब्डा लिख ​​सकते हैं जैसे bound(0) और bound(0L) अलग-अलग व्यवहार करते हैं।

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