2009-04-09 18 views
6

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

std::for_each(vec.begin(), vec.end(), Foo()) 

और यह खूबसूरत है और ठीक:

उदाहरण के लिए यदि आप एक std::vector है और वेक्टर के प्रत्येक आइटम पर एक कार्रवाई करना चाहते हैं, अपना पहला विचार यह उपयोग करने के लिए है। लेकिन फिर बग रिपोर्ट का पहला सेट आता है और आपको कोड को संशोधित करना होगा। अब आप Foo() कॉल करने के लिए पैरामीटर जोड़ना होगा, इसलिए अब यह हो जाता है:

std::for_each(vec.begin(), vec.end(), std::bind2nd(Foo(), X)) 

लेकिन यह है कि केवल अस्थायी समाधान है। अब परियोजना परिपक्व हो रही है और आप व्यवसाय तर्क को बेहतर समझते हैं और आप कोड में नए संशोधन जोड़ना चाहते हैं। यह इस बिंदु पर है कि आपको एहसास है कि आपको पुराने अच्छे का उपयोग करना चाहिए:

for(std::vector::iterator it = vec.begin(); it != vec.end(); ++it) 

क्या यह केवल मेरे लिए हो रहा है? क्या आप अपने कोड में इस तरह के पैटर्न को पहचानते हैं? क्या आपने STL का उपयोग करके समान एंटी-पैटर्न का अनुभव किया है?

+1

बीटीडब्ल्यू, यदि आपके दूसरे उदाहरण में, "एक्स" सभी तत्वों के लिए समान है। बस इसे फू के कन्स्ट्रक्टर को पास करें और इसे बाध्य करने के बजाए इसे मजेदार में स्टोर करें। बहुत आसान –

+0

आप वास्तव में एसटीएल का उपयोग नहीं कर रहे हैं, इसलिए आप सुरक्षित हैं :) –

+0

बस एक राय है, लेकिन "बहुत अधिक" तब होती है जब आप उन सुविधाओं का उपयोग करते हैं जिन्हें आपको पूरी तरह से उपयोग करने के लिए आवश्यकता नहीं होती है। यदि यह सहायक है, तो इसका इस्तेमाल करें। यदि आप अत्यधिक लंबे नामों के बारे में चिंतित हैं, तो आप हमेशा उन्हें टाइप करने के लिए टाइपिफ़ या नेमस्पेस उपनाम का उपयोग कर सकते हैं (उदाहरण के लिए, 'typedef std :: vector :: iterator VecIter; ')। मानक लाइब्रेरी के साथ बात यह है कि यह आमतौर पर किसी दिए गए कंपाइलर पर कुछ करने का सबसे सामान्य सामान्य मामला तरीका है, क्योंकि केवल कंपाइलर के निर्माता या जो लोग इसे सर्वश्रेष्ठ जानते हैं (यदि निर्माता नहीं हैं) इसके कार्यान्वयन को लिखेंगे। उपयोगी होने पर इसका उपयोग करने से डरो मत। –

उत्तर

10

boost::bind का उपयोग std :: for_each के साथ इस समस्या को एक साफ तरीके से हल करता है। या आप BOOST_FOREACH का उपयोग कर सकते हैं। std :: for_each की

उदाहरण:

std::for_each(v.begin(), v.end(), boost::bind(&C::f, _1, param)); 

BOOST_FOREACH का उदाहरण:

std::list<int> list_int(/*...*/); 
BOOST_FOREACH(int i, list_int) 
{ 
    // do something with i 
} 
+0

... जब तक आप 10 पैरामीटर नहीं प्राप्त करते, वह है! :) – Kylotan

+1

जिस बिंदु पर आप उन्हें एक संरचना के भीतर एक साथ समूहित करते हैं :) –

+2

नहीं, जिस बिंदु पर आप उस आर्किटेक्चर पर पुनर्विचार करते हैं जिसके लिए एक फ़ंक्शन की आवश्यकता होती है जिसमें 10 पैरामीटर हों;) –

3

आपकी समस्या की तरह, मैं अक्सर देखते हैं कि "functor" पैटर्न/C++ में मुहावरा वास्तव में काफी है बोझल। यही कारण है कि मैं सी ++ 0 एक्स में Lambda Functions की प्रतीक्षा कर रहा हूं। उनमें से कुछ अब boost :: lambda के साथ संभव है।

+0

ओएमजी, सिंटैक्स है ... 0X में 8 और महीने हैं जब तक कि यह 3+ साल तक समाप्त न हो जाए जब तक कि प्रमुख कंपाइलर विक्रेता न हों। यह एक लंबा समय होगा। –

+1

@ एंटन: यह पहले से ही जी ++ और विजुअल स्टूडियो 10 (आरसी मुक्त रूप से उपलब्ध है) –

10

हालांकि यह विपरीत तरीके से भी जा सकता है। मान लें कि आप एक ऑपरेशन के साथ शुरू करते हैं जो केवल कुछ लाइनें लेता है। आप एक समारोह है कि केवल एक बार कहा जाएगा, बस पाश गाढ़ा करने के लिए बनाने परेशान करने के लिए नहीं करना चाहते, तो आप की तरह कुछ लिखें:

for() 
{ 
    // do 
    // some 
    // stuff 
} 

फिर आपरेशन आप प्रदर्शन करने के लिए और अधिक जटिल हो जाता है, आपको लगता है की जरूरत के रूप में अपने मूल विधि की तरह बनना है कि यह एक अलग समारोह में खींच समझ में आता है तो आप

for() 
    do_alot_more_stuff(); 

और फिर इसे संशोधित करने के साथ खत्म आगे इसे नीचे गाढ़ा करने के लिए समझ में आता है:

std::for_each(begin, end, do_alot_more_stuff); 

अंत में, लूप के लिए वास्तव में for_each को बदलने में कितना मुश्किल है, या इसके विपरीत? छोटे विवरणों पर खुद को मत मारो!

5

इसे किसी अन्य भाषा उपकरण की तरह उपयोग करें। जब यह आपके जीवन को आसान बनाता है, तो इसका इस्तेमाल करें। जब यह बोझिल हो जाता है, तो कुछ और करें। ऐसा नहीं है कि जब आवश्यकताएं बदलती हैं, तो एक लूप को एक या दूसरे तरीके से दोबारा प्रतिक्रिया देना मुश्किल होता है।

+0

बिल्कुल है। कोड बदलने के साथ क्या गलत है? –

0

समांतरता के बारे में भी सोचें, एक फ़ंक्शन के साथ आप यह निर्धारित कर सकते हैं कि क्या बदलेगा और यह इंगित करेगा कि तत्वों की एक श्रृंखला प्रारंभिक से एक समय में समानांतर में 1 की बजाय हो सकती है।

1

शायद तुम बजाय for_each इस्तेमाल किया पहली जगह में परिणत ...

1

मैं का उपयोग कभी नहीं std :: for_each (या बहुत ही कम)।

मैं अब Boost.Foreach और क्लासिक "के लिए" निर्माण का उपयोग करने का सुझाव दूंगा। और जब सी ++ 0x बाहर हो जाता है, तो आप नए "के लिए" निर्माण का उपयोग करने पर विचार कर सकते हैं, जो कंटेनरों के माध्यम से पुनरावर्तित करने के लिए अधिक पठनीय बनाते हैं।

+1

वास्तविक "के लिए" लूप प्राप्त करने के लिए सी ++ के लिए शायद ही इंतजार कर सकते हैं (इसके बजाए गौरवशाली होने के बजाए अब यह लूप है)। –

0

या आप C++ 0x लिए प्रतीक्षा करें और for(elem& e, container){e.something();}
काफी ही उपयोग BOOST_FOREACH() के रूप में हो सकता है, लेकिन मानक का हिस्सा (कुछ वर्षों में ...)।

2

मुझे एल्गोरिदम में बहुत सी चीजों के साथ एक ही समस्या है। और कोड होने के कारण यह एक पुरानी प्रवृत्ति है जो सिर्फ लूप के लिए पुरानी शैली का उपयोग कर रही है।

मैं वास्तव में उचित निर्माता और विनाशक के साथ कुछ विशेष मज़ेदार वर्ग (जो कि सी ++ में एक मामूली उन्नत विषय है, जो कि मेरे कई रखरखाव पूरी तरह से समझ नहीं पाएंगे) बनाने के लिए वास्तव में औचित्य साबित नहीं कर सकते हैं, और शायद कुछ एक्सेसर्स, बस लूप के लिए एक लाइन से बचने के लिए।

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