अन्य सभी उत्तरों पढ़ने के बाद, मैं यहां एक लाभ में हूं ... लेकिन यहां यह जाता है।
हालांकि यह इसके द्वारा बुलाए गए फ़ंक्शन के लिए संभव है-> दूसरा (यह); translationEvents नक्शा (आमतौर पर ही)
अगर यह सही है, कि है, से एक तत्व को दूर करने के एक कॉलबैक कंटेनर से किसी भी तत्व निकाल सकते हैं, आप संभवतः पाश से ही इस समस्या को हल नहीं कर सकते।
वर्तमान कॉलबैक
हटाया जा रहा है सरल मामले में जहां कॉलबैक केवल खुद को हटा सकते हैं में, आप विभिन्न तरीकों का उपयोग कर सकते हैं:
// [1] Let the callback actually remove itself
for (iterator it = next = m.begin(); it != m.end(); it = next) {
++next;
it->second(this);
}
// [2] Have the callback tell us whether we should remove it
for (iterator it = m.begin(); it != m.end();) {
if (!it->second(this)) { // false means "remove me"
m.erase(it++);
} else {
++it;
}
}
इन दो विकल्पों के अलावा, मैं स्पष्ट रूप से पसंद करेंगे [2 ], क्योंकि आप हैंडलर के कार्यान्वयन से कॉलबैक को डीकॉप्लिंग कर रहे हैं। यही है, [2] में कॉलबैक उस कंटेनर के बारे में कुछ भी नहीं जानता जिसमें यह आयोजित किया जाता है। [1] में एक उच्च युग्मन है (कॉलबैक कंटेनर के बारे में जानता है) और कोड के कई स्थानों से कंटेनर बदल दिया गया है, इसके बारे में तर्क करना मुश्किल है।कुछ समय बाद आप भी कोड पर वापस लग सकता है, लगता है कि यह एक अजीब पाश है (याद नहीं है कि कॉलबैक खुद को हटाता है) और अधिक कुछ में यह refactor समझदारfor (auto it = m.begin(), end = m.end(); it != end; ++it) it->second(this);
रूप
अन्य कॉलबैक
हटाया जा रहा है
की अधिक जटिल समस्या के लिए कोई अन्य कॉलबैक हटा सकता है, यह सब आपके द्वारा किए गए समझौतों पर निर्भर करता है। सरल मामले में, जहां यह केवल पूरा यात्रा के बाद अन्य कॉलबैक को हटा में, तो आपको एक अलग सदस्य समारोह है कि तत्वों को दूर करने के रखना होगा प्रदान कर सकते हैं, और फिर उन्हें एक बार में सभी को दूर करने के बाद पाश पूरे करता है:
void removeElement(std::string const & name) {
to_remove.push_back(name);
}
...
for (iterator it = m.begin(); it != m.end(); ++it) {
it->second(this); // callback will possibly add the element to remove
}
// actually remove
for (auto it = to_remove.begin(); it != to_begin.end(); ++it) {
m.erase(*it);
}
यदि तत्वों को हटाने की तत्काल आवश्यकता है (यानी उन्हें इस पुनरावृत्ति में भी नहीं कहा जाना चाहिए यदि उन्हें अभी तक नहीं कहा गया है), तो आप यह जांच करके उस दृष्टिकोण को संशोधित कर सकते हैं कि कॉल को निष्पादित करने से पहले इसे हटाने के लिए चिह्नित किया गया था या नहीं। निशान दो तरीकों से किया जा सकता है, जिसमें से जेनेरिक कंटेनर में मान प्रकार को pair<bool,T>
होने के लिए बदल देगा, जहां बूल इंगित करता है कि यह जीवित है या नहीं। , तो इस मामले में के रूप में, निहित वस्तु बदला जा सकता है आप सिर्फ इतना है कि कर सकता है:
void removeElement(std::string const & name) {
auto it = m.find(name); // add error checking...
it->second = TranslationFinished(); // empty functor
}
...
for (auto it = m.begin(); it != m.end(); ++it) {
if (!it->second.empty())
it->second(this);
}
for (auto it = m.begin(); it != m.end();) { // [3]
if (it->second.empty())
m.erase(it++);
else
++it;
}
ध्यान दें कि जब से एक कॉलबैक निकाल सकते हैं कंटेनर में किसी भी तत्व, आप के रूप में तुम जाओ नहीं मिटा सकते हैं, के रूप में वर्तमान कॉलबैक को पहले से ही देखे गए इटरेटर को हटा सकता है। फिर फिर, आप थोड़ी देर के लिए खाली मज़ेदारों को छोड़ने की परवाह नहीं कर सकते हैं, इसलिए यह ठीक है कि आप इसे अनदेखा करें और erase
प्रदर्शन करते समय निष्पादित करें। तत्वों को पहले से ही देखा गया है जिन्हें हटाने के लिए चिह्नित किया गया है, अगले पास में साफ़ कर दिया जाएगा।
सी # के संग्रह कक्षाएं इस संबंध में भयानक हैं। अगर वे संशोधित होते हैं तो वे * सबकुछ * को अमान्य करते हैं। सी ++ कंटेनर आमतौर पर इस संबंध में बहुत बेहतर व्यवहार करते हैं, और आम तौर पर केवल विशिष्ट इटरेटर्स को अमान्य कर देते हैं, ताकि आप – jalf