2011-09-03 8 views
5

उदाहरण के लिए:क्यों प्रत्येक संग्रह प्रकार के लिए stl में for_each सदस्य फ़ंक्शन नहीं है?

v.for_each([](int i) { printf("%d\n", i); }); 

अगर कहीं अधिक सुंदर और सामान्य रूप से प्रयुक्त की तुलना में पठनीय:

std::for_each(v.begin(), v.end(), [](int i) { printf("%d\n", i); }); 

वहाँ किसी वैध कारण के इस तरह के एक सदस्य समारोह मानक से लापता है है?

+0

आप इसे क्यों की आवश्यकता होगी? सदस्य कार्य केवल उद्देश्य को पूरा करते हैं यदि कार्यान्वयन को और अधिक कुशल बनाया जा सकता है (सेट :: खोज एक सेट पर std :: find() से अधिक कुशल है)।ओह, और यदि आप सर्वव्यापी '.begin()', en '.end()' कॉल से बचना चाहते हैं, तो [बूस्ट रेंज एल्गोरिदम] का उपयोग करें (http://www.boost.org/doc/libs/1_47_0/libs/ रेंज/doc/html/रेंज/संदर्भ/एल्गोरिदम/introduction.html)। मीठे सिंटैक्टिक चीनी – sehe

+0

@sehe: या * कम * कुशल, जैसे 'std :: list :: sort() ':-) –

+0

@ केरेक:' std :: list :: sort' विशेष है,' std :: sort' 'RandomAccessIterator' की आवश्यकता है, इसलिए यह सूचियों के लिए काम नहीं कर सका। –

उत्तर

8

यह संपूर्ण पुस्तकालय के लिए मानक डिजाइन तर्क है: एल्गोरिदम से अलग कंटेनर।

यदि आपने इसे अपना रास्ता दिया है, तो आपको प्रत्येक कंटेनर वाई के लिए प्रत्येक फीचर एक्स को लागू करना होगा, यदि आपके पास एम फीचर्स और एन कंटेनर हैं तो एम * एन कार्यान्वयन के लिए अग्रणी है।

इटरेटर्स का उपयोग करके और एल्गोरिदम कंटेनर के बजाय इटरेटर्स पर काम करते हैं, आपको केवल एम एल्गोरिदम प्लस एन इटरेटर इंटरफेस को लागू करना होगा।

यह अलगाव भी मतलब है कि आप आवेदन की असीम व्यापक गुंजाइश है: एल्गोरिदम बस हर पुस्तकालय कंटेनर के लिए इस्तेमाल नहीं किया जा सकता है, लेकिन किसी भी कंटेनर, वर्तमान या भविष्य, कि किसी को भी लिख सकते हैं और iterators के साथ लैस करने के लिए फैसला करता है के लिए । Finite बनाम अनंत पुन: उपयोग काफी मजबूत तर्क है! और जेनेरिक, फ्री इंटरफेस के माध्यम से एल्गोरिदम को कॉल करने से कोई कीमत नहीं बढ़ती है।

+0

मिक्सिन का उपयोग इस समस्या को कम करने के लिए किया जा सकता है- आप एक कार्यक्षमता मिश्रण लिख सकते हैं जो सामान्य * और * किसी भी कंटेनर पर काम करता है। – Puppy

+0

@DeadMG: आप नियमित अभिव्यक्ति मिलान या निर्देशिका ट्रैवर्सल का संग्रह कहने के लिए मिश्रण करने का उपयोग कैसे करेंगे? –

+0

कंटेनर मिश्रित से विरासत में मिलता है, जो कार्यक्षमता प्रदान करने के लिए हुड के नीचे इटरेटर का उपयोग करता है। जब तक ऑब्जेक्ट इटरेटर प्रदान करता है- ठीक उसी तरह - जैसा कि वे अब करते हैं- तो मिक्सिन उस समर्थन को ओपी में दिखाए गए इंटरफेस के साथ सरल सदस्य कार्यों में परिवर्तित कर सकता है। इसके अतिरिक्त, यह वास्तव में * अधिक * जेनेरिक है क्योंकि यदि आपको आवश्यकता है तो आप कंटेनर क्लास में कार्यक्षमता को ओवरराइड कर सकते हैं- उदाहरण के लिए, 'std :: list'। – Puppy

1

साधारण तथ्य यह है कि मानक लाइब्रेरी डिज़ाइन उस समय से होता है जब भाषा कई विशेषताओं की पेशकश नहीं करती है, और सीआरटीपी आधारित मिश्रित जैसे कई डिज़ाइन सामान्य नहीं थे। इसका मतलब यह है कि मानक डिज़ाइन जो अब स्पष्ट हैं, मानक लाइब्रेरी बनने पर बस कार्यान्वित या डिजाइन योग्य नहीं थे।

इटरेटर एक महान सामान्य कार्यान्वयन करते हैं, लेकिन वे एक चतुर सामान्य इंटरफ़ेस बनाते हैं। मुझे यह दुख हुआ कि लाइब्रेरी डिज़ाइन के साथ समस्या को हल करने और इसे ओवरहाल करने के बजाय, उन्होंने समस्या के एक छोटे से सबसेट के लिए एक विशेष केस भाषा सुविधा पेश की।

+0

क्या आप एक मिश्रण का एक छोटा सा उदाहरण दिखा सकते हैं जो भविष्य के कंटेनर और भविष्य के एल्गोरिदम के अनुकूल हो सकता है? –

+0

@ केरेक: इसे करने की ज़रूरत नहीं है। हम भविष्य के एल्गोरिदम के लिए मौजूदा समर्थन का उपयोग कर सकते हैं, भविष्य के कंटेनर केवल इससे प्राप्त कर सकते हैं, और हम सबसे अधिक उपयोग किए जाने वाले एल्गोरिदम के लिए कुछ बेहतर प्राप्त कर सकते हैं। – Puppy

+0

मैं देखता हूं। अच्छा, यह पेशकश करना अच्छा लगेगा। इस तरह लगता है एक वैकल्पिक सुविधा सेट के रूप में जोड़ा जा सकता है ... –

2
template <class InputIterator, class UnaryFunction> 
UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f); 

आप देख सकते हैं for_each पैरामीटर में के रूप में इनपुट इटरेटर लेता है, इसलिए किसी भी STL कंटेनर है कि एक इनपुट इटरेटर संगत प्रदान कर सकते हैं (इनपुट इटरेटर से अलग अर्थ है, यह भी द्विदिश, रैंडम एक्सेस इटरेटर आदि हो सकता है) होगा std :: for_each के साथ संगत। इस तरह से डिजाइन करके, डेटा प्रकार (कंटेनर) से एसएलएल जेनेरिक अलग एल्गोरिदम जो अधिक सुरुचिपूर्ण & जेनेरिक है।

0

आपको इसकी आवश्यकता क्यों होगी?

सदस्य कार्य केवल उद्देश्य को पूरा करते हैं यदि कार्यान्वयन को और अधिक कुशल बनाया जा सकता है (सेट :: ढूंढ एक सेट पर std :: find() से अधिक कुशल है)।

पुनश्च ओह, और आप हर जगह का .begin() से बचने के लिए, एन .end() कॉल, Boost Range Algorithms का उपयोग करना चाहते हैं। मीठे वाक्यात्मक चीनी

एक यादृच्छिक बूस्ट रेंज प्रेरित नमूना:

#include <boost/range/adaptors.hpp> 
#include <boost/range/algorithm.hpp> 
#include <boost/pending/integer_range.hpp> 

using namespace boost::adaptors; 

static int mod7(int v) 
    { return v % 7; } 

int main() 
{ 
    std::vector<int> v; 

    boost::copy(
      boost::make_integer_range(1,100) | transformed(mod7), 
      std::back_inserter(v)); 

    boost::sort(v); 

    boost::copy(
      v | reversed | uniqued, 
      std::ostream_iterator<int>(std::cout, ", ")); 
} 
संबंधित मुद्दे