लेकिन क्यों बाध्य होगा इस तरह से डिजाइन किया जाना है कि इस संकलित:
auto g = std::bind(&Foo::baz, &foo);
मैं f
कॉल कर सकते हैं, लेकिन मैं कभी g
फोन नहीं कर सकते हैं। यह संकलन क्यों करें?
Boost.Bind FAQ का कहना है कि Boost.Bind आमतौर पर "बाँध समय" पर ऐसी त्रुटियों का निदान होगा (लाइन जहां bind
फोन पर अर्थात)। हालांकि मानक की आवश्यकता नहीं है कि std::bind
के लिए, बजाय यह है में निम्नलिखित std::bind
के लिए तत्व आवश्यक है:
INVOKE (fd, w1, w2, ..., wN)
(20.9.2) कुछ मान w1 के लिए एक वैध अभिव्यक्ति, W2 होगा, ..., डब्ल्यूएन, जहां N == sizeof...(bound_args)
।
इसका मतलब है कि आपका कोड फ़ंक्शन की पूर्व शर्त का उल्लंघन करता है, जिसके परिणामस्वरूप अपरिभाषित व्यवहार होता है। मानक पुस्तकालय कार्यान्वयन पूर्व शर्त उल्लंघन की जांच करने के लिए बाध्य नहीं है, यह आपका काम है। लाइब्रेरी को इन्हें जांचने के लिए मना नहीं किया गया है, इसलिए यह इसे अस्वीकार करने के कार्यान्वयन के अनुरूप होगा, बूस्ट के रूप में। बाइंड करता है। मैं आपके पुस्तकालय विक्रेता से अनुरोध करता हूं कि वे अवैध बाध्य अभिव्यक्तियों का निदान करने के लिए कहें जहां ऐसा करना संभव है, "कार्यान्वयन की गुणवत्ता" वृद्धि के रूप में।
क्यों नहीं बस यह बताए बिना डिफ़ॉल्ट पास सभी सही क्रम में तर्क है?
मैं दो कारणों से सोच सकता हूं।
सबसे पहले, bind
द्वारा बनाई गई कॉल आवरण के व्यवहार तर्क है कि एक प्लेसहोल्डर के अनुरूप नहीं है ड्रॉप करने के लिए है, तो आप x(1, 2, 3)
फोन और यह सभी तर्क पर ध्यान न दें और foo.bar()
फोन हो सकता है। यह एक सामान्य पैटर्न का हिस्सा है जहां आप bind
का उपयोग करके एक एन-एरीटी फ़ंक्शन को एक पूरी तरह से अलग धैर्य के साथ कॉल रैपर बनाने के लिए लपेट सकते हैं जो तर्क जोड़ सकता है, उन्हें हटा सकता है, कुछ विशिष्ट बाध्य मानों को ठीक कर सकता है।x(1, 2, 3)
सभी तर्कों को छोड़ना असंभव होगा यदि डिफ़ॉल्ट व्यवहार में कोई प्लेसहोल्डर्स का उपयोग नहीं किया जाता है, तो सभी तर्कों को आगे बढ़ाना था।
दूसरा, यह हमेशा आपको यह सुनिश्चित करने के लिए अधिक सुसंगत है कि आप किस तर्क में पारित करना चाहते हैं। आम तौर पर जब कोई बाध्य तर्क नहीं होता है तो सभी आमंत्रण तर्कों को पारित करने के लिए केवल समझदारी होगी, अन्यथा bind
को कैसे पता होना चाहिए कि बाध्य तर्कों के पहले या बाद में आमंत्रण तर्क पारित करना है या नहीं?
उदा।
struct X {
void f(int, int) { }
} x;
auto h = bind(&X::f, &x, 1);
h(2);
दिया चाहिए x.f(1, 2)
या x.f(2, 1)
में h(2)
परिणाम के लिए कॉल? जब सही तर्क होते हैं तो सही व्यवहार स्पष्ट नहीं होता है, जब सभी प्लेसमेंटधारक नहीं होते हैं तो स्वचालित रूप से सभी तर्कों को अग्रेषित करते हैं, जब कोई बाध्य तर्क नहीं होता है (क्योंकि तब कोई सवाल नहीं है कि बाध्य तर्क पहले या आखिरी आते हैं या नहीं) , जो एक काफी विशेष मामला है। उस विशेष मामले के साथ काम करने के लिए एपीआई की एक महत्वपूर्ण विशेषता को बदलना संदिग्ध मूल्य होगा, खासकर जब यह x(1, 2, 3)
->foo.bar()
केस प्राप्त करना असंभव है।
एक वैकल्पिक समाधान यह है कि उपयोगकर्ताओं को जो कुछ चाहिए, उसके बारे में स्पष्ट होना आवश्यक है, लेकिन N4171 में टॉमसज़ कमीन्स्की द्वारा प्रस्तावित "बस कुछ भी आगे" कहने का एक स्पष्ट तरीका प्रदान करें, जिस पर सी ++ कमेटी मीटिंग में चर्चा की जाएगी सप्ताह। _all
प्लेसहोल्डर तय मंगलाचरण तर्कों से पहले या बाध्य तर्क के बाद आना चाहिए, क्योंकि आप स्पष्ट रूप से कह सकते हैं कि क्या आप चाहते हैं की समस्या का हल bind(f, arg1, arg2, std::placeholders::_all)
या bind(f, std::placeholders::_all, arg1, arg2)
या यहाँ तक कि bind(f, arg1, std::placeholders::_all, arg2)
शायद
क्योंकि वहाँ तर्क की संख्या प्राप्त करने के लिए कोई रास्ता नहीं है अन्यथा फ़ंक्शन का अर्थ है, जिसका अर्थ है कि जेनरेट किए गए फ़ंक्शन ऑब्जेक्ट को * किसी भी * तर्कों की संख्या को अनुमति देना होगा, जिसमें कोई भी शामिल नहीं है, जो अपरिभाषित व्यवहार का कारण बनता है (उदाहरण के लिए) 'g' को बिना तर्क के "कहा जाता है। –
मुझे लगता है कि 'std :: प्लेसहोल्डर्स' दो कार्य करता है, 1. जैसा कि आप कहते हैं, वे स्रोत से सिंक तक तर्कों को रूट करते हैं, 2. वे इंगित करते हैं कि कितने तर्क की आवश्यकता है। – Niall
बूस्ट लाइब्रेरी में 'बाइंड' से संबंधित मूल डिजाइन तर्क अधिक हो सकता है। – Niall