इस दोष रिपोर्ट के समाधान में प्रश्न (और अधिकांश उत्तर) पोस्ट किए जाने के बाद से मानक बदल दिया गया है ।
for(:)अपने प्रकार पर एक पाश काम करने का तरीका Xअब दो तरीकों में से एक है:
सदस्य बनाएं X::begin()और X::end()कुछ ऐसा करें जो एक पुनरावृत्त की तरह काम करता है
एक निशुल्क फ़ंक्शन बनाएं begin(X&)और end(X&)कुछ ऐसा Xलौटाएं जो इट्रेटर की तरह काम करता हो, आपके प्रकार के समान नामस्थान में ।¹
और constविविधताओं के लिए भी ऐसा ही है । यह उन दोनों कंपाइलरों पर काम करेगा जो दोष रिपोर्ट परिवर्तनों को लागू करते हैं, और ऐसे कंपाइलर जो नहीं करते हैं।
लौटाई गई वस्तुओं को वास्तव में पुनरावृत्त होना नहीं है। for(:)पाश, सी ++ मानक के अधिकांश भागों के विपरीत, है कुछ बराबर करने के लिए विस्तार करने के लिए निर्दिष्ट :
for( range_declaration : range_expression )
हो जाता है:
{
auto && __range = range_expression ;
for (auto __begin = begin_expr,
__end = end_expr;
__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
जहां चर के साथ शुरुआत __ही प्रदर्शनी के लिए कर रहे हैं, और begin_exprऔर end_exprजादू है कि कॉल begin/ end.²
आरंभ / समाप्ति वापसी मूल्य पर आवश्यकताएं सरल हैं: आपको पूर्व-अधिभार देना होगा ++, यह सुनिश्चित करना होगा कि आरंभिक अभिव्यक्तियाँ मान्य हैं, बाइनरी !=जिसका उपयोग बूलियन संदर्भ में किया जा सकता है, एकात्मक *जो कुछ ऐसा देता है जिसे आप असाइन कर सकते हैं- range_declarationऔर सार्वजनिक रूप से उजागर कर सकते हैं नाशक।
इस तरह से ऐसा करना जो एक पुनरावृत्त के साथ संगत नहीं है, शायद एक बुरा विचार है, क्योंकि सी ++ के भविष्य के पुनरावृत्तियों आपके कोड को तोड़ने के बारे में अपेक्षाकृत कैवेलियर हो सकते हैं यदि आप करते हैं।
एक तरफ के रूप में, यह यथोचित संभावना है कि मानक के भविष्य में संशोधन से end_exprभिन्न प्रकार की वापसी की अनुमति होगीbegin_expr । यह इस रूप में उपयोगी है कि यह "आलसी-अंत" मूल्यांकन की अनुमति देता है (जैसे कि शून्य-समाप्ति का पता लगाना) जो हाथ से लिखे गए सी लूप के रूप में कुशल होने के लिए अनुकूलित करना आसान है, और इसी तरह के अन्य फायदे हैं।
¹ ध्यान दें कि for(:)लूप्स किसी भी अस्थायी स्टोर में हैंauto&& चर हैं, और इसे एक लवल्यू के रूप में पास करते हैं। आप पता नहीं लगा सकते हैं कि आप एक अस्थायी (या अन्य प्रतिद्वंद्विता) से अधिक परेशान हैं; इस तरह के अधिभार को for(:)लूप द्वारा नहीं बुलाया जाएगा । N4527 से देखें [stmt.ranged] 1.2-1.3।
-या तो कॉल begin/ endविधि, या ADL- केवल नि: शुल्क समारोह की तलाश begin/ end, या C- शैली सरणी समर्थन के लिए जादू। ध्यान दें कि std::beginजब तक range_expressionकिसी प्रकार की वस्तु वापस नहीं आती है, तब तक उसे नहीं बुलाया जाता हैnamespace std या उसी पर निर्भर है।
में c ++ 17 रेंज-फॉर एक्सप्रेशन अपडेट किया गया है
{
auto && __range = range_expression ;
auto __begin = begin_expr;
auto __end = end_expr;
for (;__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
के प्रकार के साथ __beginऔर __endविघटित हो गए हैं।
यह शुरू होने के समान अंत इटेटर को अनुमति नहीं देता है। आपका अंतिम पुनरावृत्ति प्रकार एक "प्रहरी" हो सकता है जो केवल !=आरंभिक पुनरावृत्ति प्रकार के साथ समर्थन करता है ।
यह क्यों उपयोगी है, इसका एक व्यावहारिक उदाहरण यह है कि आपका एंड इट्रेटर पढ़ सकता है " char*यह देखने के लिए कि क्या यह इंगित करता है '0'" जब आपके ==साथ char*। यह एक C ++ रेंज-फॉर-एक्सप्रेशन के लिए एक शून्य-टर्मिनेटेड char*बफर पर पुनरावृत्ति करते समय इष्टतम कोड उत्पन्न करने की अनुमति देता है ।
struct null_sentinal_t {
template<class Rhs,
std::enable_if_t<!std::is_same<Rhs, null_sentinal_t>{},int> =0
>
friend bool operator==(Rhs const& ptr, null_sentinal_t) {
return !*ptr;
}
template<class Rhs,
std::enable_if_t<!std::is_same<Rhs, null_sentinal_t>{},int> =0
>
friend bool operator!=(Rhs const& ptr, null_sentinal_t) {
return !(ptr==null_sentinal_t{});
}
template<class Lhs,
std::enable_if_t<!std::is_same<Lhs, null_sentinal_t>{},int> =0
>
friend bool operator==(null_sentinal_t, Lhs const& ptr) {
return !*ptr;
}
template<class Lhs,
std::enable_if_t<!std::is_same<Lhs, null_sentinal_t>{},int> =0
>
friend bool operator!=(null_sentinal_t, Lhs const& ptr) {
return !(null_sentinal_t{}==ptr);
}
friend bool operator==(null_sentinal_t, null_sentinal_t) {
return true;
}
friend bool operator!=(null_sentinal_t, null_sentinal_t) {
return false;
}
};
पूर्ण C ++ 17 समर्थन के बिना एक संकलक में लाइव उदाहरण ; forलूप मैन्युअल रूप से विस्तारित।
begin/endया मित्र, स्थिर या मुक्त को परिभाषित करके संभव हैbegin/end। बस सावधान रहें कि आप नि: शुल्क समारोह में किस नाम स्थान पर हैं: stackoverflow.com/questions/28242073/…