2012-11-06 7 views
18

मान लीजिए मैं एक समारोह है कि दो तर्क लेता है,बाइंड से लौटाई गई वस्तुएं अतिरिक्त तर्कों को अनदेखा क्यों करती हैं?

void f(int x, int y); 

और मैं उनमें से एक के लिए बाध्य करना चाहते हैं। इस प्रकार मैं std::bind उपयोग कर सकते हैं:

auto partiallyBoundF = std::bind(f, 10, _1); 

partiallyBoundF केवल एक तर्क लेता है, लेकिन मैं एक से अधिक के साथ यह कह सकते हैं।

partiallyBoundF(20, 0); 
partiallyBoundF(0, 44, -99, "Hello", 4.5, true, []{}); 

क्या की अनुमति वस्तुओं के उद्देश्य bind से दिया जाता है अतिरिक्त तर्क पारित होने के लिए: तर्क पहले से परे भी एक प्रकार है कि किसी भी समझ में आता है की होने के लिए नहीं है? यह त्रुटियों को संकलित करने की अनुमति देता है जिसे किसी और जगह अस्वीकार कर दिया जाएगा।

+3

क्या कंपाइलर? मुझे लगता है कि यह सिर्फ एक गैर-अनुरूप कंपेलर हो सकता है (क्योंकि उन अतिरिक्त तर्कों को वास्तव में कोई समझ नहीं आता है और मुझे संदेह है कि मानक इस अनुमति देता है)। उदाहरण के लिए एमएसवीसी अधिकतम भिन्न टेम्पलेट तर्क लेने और कुछ एनआईएल-प्रकार को डिफॉल्ट करने के लिए प्रत्येक वैरिएड टेम्पलेट को परिभाषित करके विविध टेम्पलेट्स को अनुकरण करता है। शायद ऐसा कुछ आपके व्यवहार का कारण है? –

+3

@ क्रिस्टियन राउ: यह मानक का हिस्सा है। यह भी टीआर 1 का हिस्सा था। 20.8.2/4 टिप्पणी करता है कि अपेक्षित कार्यान्वयन एक भिन्नता-टेम्पलेटलाइज्ड 'ऑपरेटर()' के लिए है जो कि जो भी पास हो गया है, उसे लेने के लिए, तर्कों के प्रकार या संख्या के बावजूद। टीआर 1 में समान शब्द है। – KnowItAllWannabe

+1

आपके मामले में, f (w1, ..., wN) जहां 'N = sizeof ... (bound_args)' (कॉल को बाध्य करने के लिए तर्कों की संख्या) मान्य अभिव्यक्ति होगी, 20.8.9.1.2/2 देखें और 20.8.2/1। संपादित करें: यह इसे कॉल करने के किसी अन्य तरीके को अस्वीकार नहीं करता है। – dyp

उत्तर

16

अतिरिक्त तर्कों को अनदेखा करना लागू करने के लिए बहुत आसान है, और वास्तव में उपयोगी हो सकता है।

एक सामान्य कार्यान्वयन में उदा। libstdC++ (g ++), लिया गया दृष्टिकोण operator() तर्कों को एक टुपल में एकत्र करना है और फिर std::placeholder बाइंड तर्कों को आवश्यकतानुसार निकालने दें। तर्क गणना लागू करने के लिए प्रयुक्त प्लेसहोल्डर की संख्या की गणना करने की आवश्यकता होगी, जो कि बहुत जटिल होगा। ध्यान दें कि बाइंड कॉल करने योग्य एकाधिक या टेम्पलेट operator() कॉल पैटर्न के साथ एक मजेदार हो सकता है, इसलिए बाइंड ऑब्जेक्ट operator() को "सही" हस्ताक्षर से उत्पन्न नहीं किया जा सकता है।

भी ध्यान रखें कि आप लिख सकते हैं:

std::bind(&foo, std::placeholders::_1, std::placeholders::_3); 

अर्थात स्पष्ट रूप से बाँध वस्तु के लिए दूसरा तर्क अनदेखी। यदि bind ने अपनी तर्क गणना लागू की है तो आपको निर्दिष्ट करने के लिए एक अतिरिक्त तरीका चाहिए। उदा। एक चौथा तर्क भी अनदेखा किया जाना था।

उपयोगिता के रूप में, एक संकेत करने के लिए एक सदस्य के संकेत हैंडलर बंधन पर विचार करें:

sig.connect(std::bind(&C::on_sig, this, param, std::placeholders::_1)); 

तो sig अतिरिक्त अवांछित उत्सर्जन मानकों, तो वे बस bind वस्तु द्वारा नजरअंदाज कर दिया जाता है; अन्यथा, एक ही हैंडलर को एकाधिक संकेतों में बाध्य करने के लिए किसी भी वास्तविक उद्देश्य के लिए एकाधिक फ़ॉरवर्डिंग रैपर लिखने की आवश्यकता नहीं होगी।

+3

"अधिक उपयोगी" - मैं उस पर बहस करता हूं। यह मजबूत टाइपिंग तोड़ता है। और यदि वांछित है, तो यह व्यवहार अभी भी एक प्रॉक्सी फिक्स्चर का उपयोग करके सख्त 'std :: bind' के साथ नकल किया जा सकता है जो विविध तर्क स्वीकार करता है। –

+2

@ कोनराड रुडॉल्फ एक बाध्य अभिव्यक्ति * सामान्य * मामले में एक अच्छी तरह से परिभाषित प्रकार नहीं है, यदि इसका कॉल करने योग्य एकाधिक 'ऑपरेटर() के साथ एक मजेदार है। – ecatmur

+0

आप लैम्ब्डा का उपयोग करके चौथे तर्क को अनदेखा कर सकते हैं। हालांकि, बहुत अच्छा नहीं है। – dyp

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