दिलचस्प पोस्ट
कैसे MySQL में एक विदेशी कुंजी बाधा अस्थायी रूप से अक्षम करने के लिए? वैल () jQuery में परिवर्तन () ट्रिगर नहीं करता है जावा में विभिन्न प्रारूपों के साथ स्ट्रिंग को पार्स करना आप प्रोग्राम को एक HTML SELECT को ड्रॉप डाउन कैसे बता सकते हैं (उदाहरण के लिए, माउसओवर के कारण)? एजेक्स पोस्ट एएसपी। नेट एमवीसी में एंटीफ़ोर्जरीटोकन शामिल हैं PHP में क्लाइंट आईपी पता कैसे प्राप्त करें? साथ ही एक सूची में कई डेटा.फ्रेमों को मर्ज कर सकते हैं छिपे हुए माता-पिता div में बाल अवकाश दिखाएं जावा में गेटो स्टेटमेंट के लिए वैकल्पिक कैसे एक एनएसटीटीटी के लिए एक क्लिक करने योग्य लिंक बनाने के लिए कोडिंग मानकों के एक सेट के खिलाफ सी / सी ++ स्रोत कोड की जांच करने के लिए एक नि: शुल्क उपकरण? scanf इनपुट के लिए दो बार पूछ रहा है जबकि मुझे उम्मीद है कि यह केवल एक बार पूछे JSON की बजाए जेनरेट किए गए HTML को लौटाने का यह एक बुरा अभ्यास क्यों है? या यह है? कैसे गतिशील रूप से एनआईटी के वेबब्राउजर या एमएसएसटीएल। एचटीएमएलडीकाट का उपयोग करते हुए एचटीएमएल कोड उत्पन्न करने के लिए? बैच स्क्रिप्ट के साथ निर्देशिका में प्रत्येक फ़ाइल में कुछ कैसे करें

आगे का उपयोग करने के फायदे

सही फ़ॉरवर्डिंग में, std::forward नामित rvalue संदर्भों t1 और t2 को अनाम rvalue संदर्भों में परिवर्तित करने के लिए उपयोग किया जाता है। ऐसा करने का क्या उद्देश्य है? यदि हम t1 और t1 को लावलुओं के रूप में छोड़ देते हैं,

 template <typename T1, typename T2> void outer(T1&& t1, T2&& t2) { inner(std::forward<T1>(t1), std::forward<T2>(t2)); } 

वेब के समाधान से एकत्रित समाधान "आगे का उपयोग करने के फायदे"

आपको अग्रेषण समस्या को समझना होगा आप संपूर्ण समस्या को विस्तार से पढ़ सकते हैं , लेकिन मैं संक्षेप में बताऊँगा

मूल रूप से, अभिव्यक्ति E(a, b, ... , c) , हम अभिव्यक्ति f(a, b, ... , c) के बराबर होना चाहते हैं। सी ++ 03 में, यह असंभव है कई प्रयास हैं, लेकिन वे सभी कुछ संबंधों में विफल होते हैं।


सबसे सरल है एक lvalue- संदर्भ का उपयोग करने के लिए:

 template <typename A, typename B, typename C> void f(A& a, B& b, C& c) { E(a, b, c); } 

लेकिन यह अस्थायी मानों को संभाल करने में विफल रहता है: f(1, 2, 3); , क्योंकि ये एक लावल्यू-संदर्भ के लिए बाध्य नहीं हो सकते।

अगले प्रयास हो सकता है:

 template <typename A, typename B, typename C> void f(const A& a, const B& b, const C& c) { E(a, b, c); } 

जो ऊपर की समस्या को हल करता है, लेकिन फ्लॉप फ्लॉप। यह अब E को गैर-तर्क तर्क प्रदान करने में विफल रहता है:

 int i = 1, j = 2, k = 3; void E(int&, int&, int&); f(i, j, k); // oops! E cannot modify these 

तीसरा प्रयास const_cast -रेफरेंस स्वीकार करता है, लेकिन फिर const_cast का const हो जाता है:

 template <typename A, typename B, typename C> void f(const A& a, const B& b, const C& c) { E(const_cast<A&>(a), const_cast<B&>(b), const_cast<C&>(c)); } 

यह सभी मान स्वीकार करता है, सभी मानों पर पारित कर सकता है, लेकिन संभवतः अपरिभाषित व्यवहार की ओर जाता है:

 const int i = 1, j = 2, k = 3; E(int&, int&, int&); f(i, j, k); // ouch! E can modify a const object! 

एक अंतिम समाधान सब कुछ ठीक से संभालता है … बनाए रखने के लिए असंभव होने की कीमत पर। आप कंस्ट्रक्शन और गैर-कॉस्ट के सभी संयोजनों के साथ f अधिभार प्रदान करते हैं:

 template <typename A, typename B, typename C> void f(A& a, B& b, C& c); template <typename A, typename B, typename C> void f(const A& a, B& b, C& c); template <typename A, typename B, typename C> void f(A& a, const B& b, C& c); template <typename A, typename B, typename C> void f(A& a, B& b, const C& c); template <typename A, typename B, typename C> void f(const A& a, const B& b, C& c); template <typename A, typename B, typename C> void f(const A& a, B& b, const C& c); template <typename A, typename B, typename C> void f(A& a, const B& b, const C& c); template <typename A, typename B, typename C> void f(const A& a, const B& b, const C& c); 

एन तर्कों के लिए 2 एन संयोजन, एक दुःस्वप्न की आवश्यकता होती है। हम इसे स्वचालित रूप से करना चाहते हैं I

(यह प्रभावी है कि हमें सी ++ 11 में संकलक को हमारे लिए क्या करना है।)


सी ++ 11 में, हमें इसे ठीक करने का मौका मिलता है। एक समाधान मौजूदा प्रकारों पर टेम्पलेट कटौती नियमों को संशोधित करता है, लेकिन यह संभावित रूप से बहुत सारे कोड को तोड़ता है इसलिए हमें एक और रास्ता खोजना होगा।

इसके बजाय नए जोड़े गए rvalue-references का उपयोग करने का समाधान है; हम rvalue- संदर्भ प्रकारों को कम करते हुए नए नियमों को पेश कर सकते हैं और कोई भी वांछित परिणाम बना सकते हैं। सब के बाद, हम संभवतः अब कोड तोड़ नहीं सकते हैं

यदि संदर्भ के संदर्भ में (नोट संदर्भ एक समाहित शब्द है जिसका अर्थ है T& दोनों), तो हम निम्नलिखित नियम का उपयोग करने के लिए प्रकार का पता लगाते हैं:

"[दिया गया] एक प्रकार टीआर जो एक प्रकार टी के संदर्भ में है," सीवी टीआर के लिए लावल्यू संदर्भ "बनाने का एक प्रयास" टाइप करने के लिए लावल्यू का संदर्भ "बनाता है, जबकि इस प्रकार" rvalue संदर्भ को बनाने का प्रयास " सीआर टीआर "प्रकार टी बनाता है।"

या सारणी रूप में:

 TR R T& & -> T& // lvalue reference to cv TR -> lvalue reference to T T& && -> T& // rvalue reference to cv TR -> TR (lvalue reference to T) T&& & -> T& // lvalue reference to cv TR -> lvalue reference to T T&& && -> T&& // rvalue reference to cv TR -> TR (rvalue reference to T) 

अगला, टेम्पलेट तर्क कटाव के साथ: यदि कोई तर्क एक lvalue A है, तो हम टेम्पलेट तर्क को ए के संदर्भ में प्रदान करते हैं। अन्यथा, हम सामान्य रूप से निकालते हैं यह तथाकथित सार्वभौमिक संदर्भ देता है (शब्द अग्रेषण संदर्भ अब आधिकारिक है)।

यह क्यों उपयोगी है? चूंकि संयुक्त हम एक प्रकार की मान श्रेणी का ट्रैक रखने की क्षमता को बनाए रखते हैं: अगर यह एक लावलू था, तो हमारे पास एक लावल्यू-रेफरेंस पैरामीटर है, अन्यथा हमारे पास एक रैवल्यू-रेफरेंस पैरामीटर है।

कोड में:

 template <typename T> void deduce(T&& x); int i; deduce(i); // deduce<int&>(int& &&) -> deduce<int&>(int&) deduce(1); // deduce<int>(int&&) 

आखिरी बात यह है कि वेरिएबल की वैल्यू श्रेणी "आगे" करना है। ध्यान रखें, फ़ंक्शन के अंदर एक बार पैरामीटर को कुछ के लिए एक लावलू के रूप में पारित किया जा सकता है:

 void foo(int&); template <typename T> void deduce(T&& x) { foo(x); // fine, foo can refer to x } deduce(1); // okay, foo operates on x which has a value of 1 

यह अच्छा नहीं है। ई को मिलते-जुलते मूल्य-श्रेणी प्राप्त करने की जरूरत है! यह समाधान है:

 static_cast<T&&>(x); 

यह क्या करता है? हम deduce समारोह के अंदर deduce , और हम एक lvalue पारित कर दिया गया है पर विचार करें इसका मतलब है T एक A& , और इसलिए स्थैतिक कलाकारों के लिए लक्ष्य प्रकार A& && , या बस A& । चूंकि x पहले से ही A& , हम कुछ नहीं करते हैं और एक लावल्यू संदर्भ के साथ छोड़ दिया जाता है।

जब हमें एक रैवल्यू पारित कर दिया गया है, T A , इसलिए स्थैतिक कलाकारों के लिए लक्ष्य प्रकार A&& कास्ट का परिणाम एक रैवल्यू अभिव्यक्ति में होता है, जो अब लैवल्यू संदर्भ के लिए नहीं जा सकता । हमने पैरामीटर की मान श्रेणी को बनाए रखा है।

ये एक साथ डालकर हमें "सही अग्रेषण" प्रदान करता है:

 template <typename A> void f(A&& a) { E(static_cast<A&&>(a)); } 

जब f एक लावलु प्राप्त करता है, E एक लावल्यू हो जाता है। जब f एक रैवल्यू प्राप्त करता है, E एक रैवल्यू हो जाता है उत्तम।


और ज़ाहिर है, हम बदसूरत से छुटकारा चाहते हैं। static_cast<T&&> याद करने के लिए गुप्त और अजीब है; इसके बजाए एक सुविधा फ़ंक्शन को forward , जो एक ही काम करता है:

 std::forward<A>(a); // is the same as static_cast<A&&>(a); 

मुझे लगता है कि std :: forward को लागू करने वाला एक संकल्पनात्मक कोड चर्चा में जोड़ सकता है यह स्कॉट मेयेर से एक स्लाइड है जो प्रभावी सी ++ 11/14 सैंपलर है

वैचारिक कोड को लागू करना std :: forward

कोड में फ़ंक्शन का कार्य std::move इस बात के लिए इसके पहले एक (कार्यान्वित) कार्यान्वयन है। मुझे फ़ाइल move.h में फ़ाइल में लिबस्टडिसी ++ में std :: forward का वास्तविक क्रियान्वयन मिला है, लेकिन यह बिल्कुल नहीं है।

उपयोगकर्ताओं के नजरिए से इसका अर्थ यह है कि std::forward एक rvalue के लिए एक सशर्त डाली है यह उपयोगी हो सकता है, अगर मैं किसी फ़ंक्शन को लिख रहा हूं जो एक पैरामीटर में एक लावलू या रैवल्यू की अपेक्षा करता है और इसे किसी अन्य समारोह में एक रेंज के रूप में पारित करना चाहता है, तभी यह एक रेंवेल के रूप में पारित किया गया हो। यदि मैंने std :: forward में पैरामीटर को लपेट नहीं किया है, तो इसे हमेशा सामान्य संदर्भ के रूप में पारित किया जाएगा।

 #include <iostream> #include <string> #include <utility> void overloaded_function(std::string& param) { std::cout << "std::string& version" << std::endl; } void overloaded_function(std::string&& param) { std::cout << "std::string&& version" << std::endl; } template<typename T> void pass_through(T&& param) { overloaded_function(std::forward<T>(param)); } int main() { std::string pes; pass_through(pes); pass_through(std::move(pes)); } 

ज़रूर, यह प्रिंट करता है

 std::string& version std::string&& version 

कोड पहले उल्लेखित टॉक से एक उदाहरण पर आधारित है। स्लाइड 10, शुरुआत से लगभग 15:00 बजे।

सही फ़ॉरवर्डिंग में, std :: forward नामित rvalue संदर्भ t1 और t2 को अनाम rvalue संदर्भ में परिवर्तित करने के लिए उपयोग किया जाता है। ऐसा करने का क्या उद्देश्य है? अगर हम टी 1 और टी 2 को लेवल्यू के रूप में छोड़ देते हैं तो यह कैसे काम करता है?

 template <typename T1, typename T2> void outer(T1&& t1, T2&& t2) { inner(std::forward<T1>(t1), std::forward<T2>(t2)); } 

यदि आप एक अभिव्यक्ति में एक नामांकित rvalue संदर्भ का उपयोग करते हैं तो यह वास्तव में एक लावलु है (क्योंकि आप नाम से ऑब्जेक्ट का संदर्भ देते हैं)। निम्नलिखित उदाहरण पर विचार करें:

 void inner(int &, int &); // #1 void inner(int &&, int &&); // #2 

अब, अगर हम इस तरह outer कहते हैं

 outer(17,29); 

हम चाहेंगे कि 17 और 29 को # 2 के लिए अग्रेषित किया जाए क्योंकि 17 और 29 पूर्णांक लिटरल हैं और जैसे कि रैवल्यूज़ लेकिन अभिव्यक्ति में t1 और t1 बाद से inner(t1,t2); लावलुओं हैं, आप # 2 की जगह # 2 की जगह ले रहे होंगे यही कारण है कि हमें संदर्भों को वापस अज्ञात संदर्भों में std::forward साथ बदलना होगा। इसलिए, t1 1 में outer में t1 1 हमेशा एक लावल्यू अभिव्यक्ति है, जबकि forward<T1>(t1) T1 आधार पर एक रैवल्यू एक्सप्रेशन हो सकता है। बाद में केवल एक लावल्यू अभिव्यक्ति है अगर T1 एक लावल्यू संदर्भ है। और T1 केवल एक लावल्यू संदर्भ होने का अनुमान लगाया है, यदि बाहरी तर्क को बाहरी रूप से एक लावल्यू अभिव्यक्ति है।

अगर हम टी 1 और टी 2 को लावल्यू के रूप में छोड़ देते हैं तो यह कैसे कहा जाता है कि फ़ंक्शन को प्रभावित किया जाए?

यदि, तत्काल होने के बाद, T1 प्रकार के प्रकार का char , और T2 एक वर्ग का होता है, आप प्रति प्रति t1 और const संदर्भ में T2 पास करना चाहते हैं। ठीक है, जब तक कि inner() उन्हें प्रति गैर संदर्भ संदर्भ लेता है, वह है, जिस स्थिति में आप ऐसा करना चाहते हैं, भी।

outer() कार्यों का एक सेट लिखने की कोशिश करें, जो बिना किसी रैवल्यू संदर्भों को लागू करते हैं, inner() के प्रकार से तर्क को पारित करने का सही तरीका घटाते हैं मुझे लगता है कि आपको 2 ^ 2 में से कुछ की आवश्यकता होगी, बहस को निकालने के लिए बहुत मोटे टेम्पलेट-मेटा सामान, और सभी मामलों के लिए यह अधिकार प्राप्त करने के लिए बहुत समय।

और फिर कोई inner() के साथ आता है जो सूचक के प्रति तर्क लेता है मुझे लगता है कि अब 3 ^ 2 बनाता है (या 4 ^ 2। नरक, मुझे यह सोचने की कोशिश करने पर परेशान नहीं किया जा सकता कि const पॉइंटर फर्क पड़ेगा।)

और फिर कल्पना करें कि आप इसे पांच मानकों के लिए करना चाहते हैं। या सात

अब आप जानते हैं कि कुछ उज्ज्वल दिमाग "संपूर्ण अग्रेषण" के साथ क्यों आए: यह संकलक आपके लिए यह सब करता है

एक बिंदु जो स्पष्ट क्रिस्टल नहीं बनाया गया है वह है कि static_cast<T&&> संभालता है const T& ठीक भी है
कार्यक्रम:

 #include <iostream> using namespace std; void g(const int&) { cout << "const int&\n"; } void g(int&) { cout << "int&\n"; } void g(int&&) { cout << "int&&\n"; } template <typename T> void f(T&& a) { g(static_cast<T&&>(a)); } int main() { cout << "f(1)\n"; f(1); int a = 2; cout << "f(a)\n"; f(a); const int b = 3; cout << "f(const b)\n"; f(b); cout << "f(a * b)\n"; f(a * b); } 

पैदा करता है:

 f(1) int&& f(a) int& f(const b) const int& f(a * b) int&& 

ध्यान दें कि 'एफ' को एक टेम्पलेट फंक्शन होना चाहिए। अगर यह 'void f (int && a)' के रूप में परिभाषित है, तो यह काम नहीं करता है