दिलचस्प पोस्ट
jqGrid और गतिशील कॉलम बाइंडिंग मैक्रो वैल्यू का स्ट्रिंगफिकेशन मैं ऑवैइडटाबलऑब्जेक्ट का उपयोग कैसे करूं? पायथन 2 में, '/' और '//' के बीच अंतर क्या होता है जब विभाजन के लिए उपयोग किया जाता है? आप एक जावा सबलेट से JSON ऑब्जेक्ट कैसे वापस करते हैं क्लाइंट पीसी पर लोकलडीबी परिनियोजन प्रोग्राम बैकस्टैक्स में पिछले खंड पर वापस जाएं कुछ फ़ील्ड पर डुप्लिकेट ढूंढने के लिए कथन चुनें निर्धारित करें कि क्या JSON एक JSONObject या JSONArray है क्या मैं दूसरी फ़ाइल से चर का उपयोग कर सकता हूं? कैसे CPU उपयोग सी # में प्राप्त करने के लिए? PHP में पूर्ण यूआरएल प्राप्त करें PHP को महीने के लिए सप्ताह की संख्या मिलती है एंड्रॉइड.एफ़। फ्रेगमेंट और एंड्रॉइड। Support.v4.app.Fragment के बीच का अंतर JSlider के स्लाइडर आइकन को चित्रित करना

कैसे कस्टम इटरेटर और const_iterators सही ढंग से लागू करने के लिए?

मेरे पास कस्टम कंटेनर क्लास है जिसके लिए मैं iterator और const_iterator क्लासेस लिखना चाहता हूं।

मैंने पहले कभी ऐसा नहीं किया और मैं एक उपयुक्त कैसे-कैसे ढूंढने में विफल रहा Iterator सृजन के बारे में दिशा निर्देश क्या हैं, और मुझे किस बारे में पता होना चाहिए?

मैं भी कोड दोहराव से बचना चाहूंगा (मुझे लगता है कि const_iterator और iterator कई चीजें साझा करते हैं, क्या एक दूसरे को उप-वर्ग चाहिए?)।

फुट नोट: मुझे पूरा यकीन है कि बूस्ट में इसे कम करने के लिए कुछ है, लेकिन मैं इसे यहां कई बेवकूफ कारणों से नहीं इस्तेमाल कर सकता हूं

वेब के समाधान से एकत्रित समाधान "कैसे कस्टम इटरेटर और const_iterators सही ढंग से लागू करने के लिए?"

  • इरेटरेटर का प्रकार चुनें, जो आपके कंटेनर में फिट बैठता है: इनपुट, आउटपुट, अग्रेषित आदि।
  • मानक लाइब्रेरी से बेस इटरेटर कक्षाओं का उपयोग करें उदाहरण के लिए, std::iterator को random_access_iterator_tag साथ। यह आधार वर्ग सभी प्रकार की परिभाषा को परिभाषित करता है जो एसटीएल द्वारा आवश्यक है और अन्य कार्य करते हैं।
  • कोड दोहराव से बचने के लिए इटरेटर क्लास एक टेम्पलेट क्लास होना चाहिए और "मान प्रकार", "सूचक प्रकार", "संदर्भ प्रकार" या उन सभी (कार्यान्वयन पर निर्भर करता है) द्वारा पैरामेट किया जाना चाहिए। उदाहरण के लिए:

     // iterator class is parametrized by pointer type template <typename PointerType> class MyIterator { // iterator class definition goes here }; typedef MyIterator<int*> iterator_type; typedef MyIterator<const int*> const_iterator_type; 

    सूचना iterator_type और const_iterator_type प्रकार की परिभाषाएं: वे आपके गैर-कॉन्स्ट और कॉन्स्ट iterators के प्रकार हैं

यह भी देखें: मानक पुस्तकालय संदर्भ

मैं आपको यह दिखाता हूं कि आप अपने कस्टम कंटेनरों के लिए आसानी से इटेरेटर्स कैसे परिभाषित कर सकते हैं, लेकिन अगर मैंने सी ++ 11 लाइब्रेरी बनाई है, तो आपको आसानी से कंटेनर के किसी भी प्रकार के कंटेनर, गैर constiguous।

आप इसे गिटूब पर https://github.com/navyenzo/blIteratorAPI पर पा सकते हैं

कस्टम इटरेटर बनाने और उनका उपयोग करने के लिए यहां सरल कदम हैं:

  1. अपना "कस्टम इटरेटर" वर्ग बनाएं
  2. अपने "कस्टम कंटेनर" वर्ग में टाइप किए गए एफिफ़ को परिभाषित करें
    • पूर्व के लिए: typedef blRawIterator< Type > iterator;
    • पूर्व के लिए: typedef blRawIterator< const Type > const_iterator;
  3. "आरंभ" "अंत" कार्य परिभाषित करें
    • पूर्व के लिए: iterator begin(){return iterator(&m_data[0]);};
    • पूर्व के लिए: const_iterator cbegin()const{return const_iterator(&m_data[0]);};
  4. हो गया था!!!

अंत में, हमारे कस्टम इटरेटर कक्षाओं को परिभाषित करने पर:

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

इस उदाहरण में, मैं एक यादृच्छिक एक्सेस इटरेटर और एक रिवर्स रैंडम एक्सेस इटरेटर परिभाषित करता हूं:

1।

 //------------------------------------------------------------------- // Raw iterator with random access //------------------------------------------------------------------- template<typename blDataType> class blRawIterator : public std::iterator<std::random_access_iterator_tag, blDataType, ptrdiff_t, blDataType*, blDataType&> { public: blRawIterator(blDataType* ptr = nullptr){m_ptr = ptr;} blRawIterator(const blRawIterator<blDataType>& rawIterator) = default; ~blRawIterator(){} blRawIterator<blDataType>& operator=(const blRawIterator<blDataType>& rawIterator) = default; blRawIterator<blDataType>& operator=(blDataType* ptr){m_ptr = ptr;return (*this);} operator bool()const { if(m_ptr) return true; else return false; } bool operator==(const blRawIterator<blDataType>& rawIterator)const{return (m_ptr == rawIterator.getConstPtr());} bool operator!=(const blRawIterator<blDataType>& rawIterator)const{return (m_ptr != rawIterator.getConstPtr());} blRawIterator<blDataType>& operator+=(const ptrdiff_t& movement){m_ptr += movement;return (*this);} blRawIterator<blDataType>& operator-=(const ptrdiff_t& movement){m_ptr -= movement;return (*this);} blRawIterator<blDataType>& operator++(){++m_ptr;return (*this);} blRawIterator<blDataType>& operator--(){--m_ptr;return (*this);} blRawIterator<blDataType> operator++(ptrdiff_t){auto temp(*this);++m_ptr;return temp;} blRawIterator<blDataType> operator--(ptrdiff_t){auto temp(*this);--m_ptr;return temp;} blRawIterator<blDataType> operator+(const ptrdiff_t& movement){auto oldPtr = m_ptr;m_ptr+=movement;auto temp(*this);m_ptr = oldPtr;return temp;} blRawIterator<blDataType> operator-(const ptrdiff_t& movement){auto oldPtr = m_ptr;m_ptr-=movement;auto temp(*this);m_ptr = oldPtr;return temp;} ptrdiff_t operator-(const blRawIterator<blDataType>& rawIterator){return std::distance(rawIterator.getPtr(),this->getPtr());} blDataType& operator*(){return *m_ptr;} const blDataType& operator*()const{return *m_ptr;} blDataType* operator->(){return m_ptr;} blDataType* getPtr()const{return m_ptr;} const blDataType* getConstPtr()const{return m_ptr;} protected: blDataType* m_ptr; }; //------------------------------------------------------------------- 

2।

 //------------------------------------------------------------------- // Raw reverse iterator with random access //------------------------------------------------------------------- template<typename blDataType> class blRawReverseIterator : public blRawIterator<blDataType> { public: blRawReverseIterator(blDataType* ptr = nullptr):blRawIterator<blDataType>(ptr){} blRawReverseIterator(const blRawIterator<blDataType>& rawIterator){this->m_ptr = rawIterator.getPtr();} blRawReverseIterator(const blRawReverseIterator<blDataType>& rawReverseIterator) = default; ~blRawReverseIterator(){} blRawReverseIterator<blDataType>& operator=(const blRawReverseIterator<blDataType>& rawReverseIterator) = default; blRawReverseIterator<blDataType>& operator=(const blRawIterator<blDataType>& rawIterator){this->m_ptr = rawIterator.getPtr();return (*this);} blRawReverseIterator<blDataType>& operator=(blDataType* ptr){this->setPtr(ptr);return (*this);} blRawReverseIterator<blDataType>& operator+=(const ptrdiff_t& movement){this->m_ptr -= movement;return (*this);} blRawReverseIterator<blDataType>& operator-=(const ptrdiff_t& movement){this->m_ptr += movement;return (*this);} blRawReverseIterator<blDataType>& operator++(){--this->m_ptr;return (*this);} blRawReverseIterator<blDataType>& operator--(){++this->m_ptr;return (*this);} blRawReverseIterator<blDataType> operator++(ptrdiff_t){auto temp(*this);--this->m_ptr;return temp;} blRawReverseIterator<blDataType> operator--(ptrdiff_t){auto temp(*this);++this->m_ptr;return temp;} blRawReverseIterator<blDataType> operator+(const int& movement){auto oldPtr = this->m_ptr;this->m_ptr-=movement;auto temp(*this);this->m_ptr = oldPtr;return temp;} blRawReverseIterator<blDataType> operator-(const int& movement){auto oldPtr = this->m_ptr;this->m_ptr+=movement;auto temp(*this);this->m_ptr = oldPtr;return temp;} ptrdiff_t operator-(const blRawReverseIterator<blDataType>& rawReverseIterator){return std::distance(this->getPtr(),rawReverseIterator.getPtr());} blRawIterator<blDataType> base(){blRawIterator<blDataType> forwardIterator(this->m_ptr); ++forwardIterator; return forwardIterator;} }; //------------------------------------------------------------------- 

अब कहीं भी अपने कस्टम कंटेनर वर्ग में:

 template<typename blDataType> class blCustomContainer { public: // The typedefs typedef blRawIterator<blDataType> iterator; typedef blRawIterator<const blDataType> const_iterator; typedef blRawReverseIterator<blDataType> reverse_iterator; typedef blRawReverseIterator<const blDataType> const_reverse_iterator; . . . public: // The begin/end functions iterator begin(){return iterator(&m_data[0]);} iterator end(){return iterator(&m_data[m_size]);} const_iterator cbegin(){return const_iterator(&m_data[0]);} const_iterator cend(){return const_iterator(&m_data[m_size]);} reverse_iterator rbegin(){return reverse_iterator(&m_data[m_size - 1]);} reverse_iterator rend(){return reverse_iterator(&m_data[-1]);} const_reverse_iterator crbegin(){return const_reverse_iterator(&m_data[m_size - 1]);} const_reverse_iterator crend(){return const_reverse_iterator(&m_data[-1]);} . . . }; 

सौभाग्य!!!

बूस्ट में मदद के लिए कुछ है: बूस्ट.इटरेटर लाइब्रेरी।

अधिक सटीक रूप से इस पृष्ठ: boost :: iterator_adaptor

बहुत दिलचस्प क्या है ट्यूटोरियल उदाहरण जो एक कस्टम कार्यान्वयन के लिए, स्क्रैच से, एक कस्टम प्रकार के लिए दिखाता है।

 template <class Value> class node_iter : public boost::iterator_adaptor< node_iter<Value> // Derived , Value* // Base , boost::use_default // Value , boost::forward_traversal_tag // CategoryOrTraversal > { private: struct enabler {}; // a private type avoids misuse public: node_iter() : node_iter::iterator_adaptor_(0) {} explicit node_iter(Value* p) : node_iter::iterator_adaptor_(p) {} // iterator convertible to const_iterator, not vice-versa template <class OtherValue> node_iter( node_iter<OtherValue> const& other , typename boost::enable_if< boost::is_convertible<OtherValue*,Value*> , enabler >::type = enabler() ) : node_iter::iterator_adaptor_(other.base()) {} private: friend class boost::iterator_core_access; void increment() { this->base_reference() = this->base()->next(); } }; 

मुख्य बिंदु, जैसा कि पहले से ही उद्धृत किया गया है, एक एकल टेम्पलेट कार्यान्वयन का उपयोग करना है और इसे typedef किया गया है

मुझे नहीं पता है कि बूस्ट में कुछ भी मददगार होगा।

मेरा पसंदीदा पैटर्न सरल है: एक टेम्पलेट तर्क ले लो जो value_type बराबर है, या तो योग्य या नहीं। यदि आवश्यक हो, तो भी एक नोड प्रकार तब, ठीक है, सब कुछ प्रकार की जगह में पड़ जाता है

बस कंप्यूटराइज़र और operator== सहित पैरामीराइजेशन (टेम्पलेट-इज़ाज़) की सभी चीज़ों को याद रखें। अधिकांश भाग के लिए, const की शब्दार्थ सही व्यवहार पैदा करेगा

 template< class ValueType, class NodeType > struct my_iterator : std::iterator< std::bidirectional_iterator_tag, T > { ValueType &operator*() { return cur->payload; } template< class VT2, class NT2 > friend bool operator== ( my_iterator const &lhs, my_iterator< VT2, NT2 > const &rhs ); // etc. private: NodeType *cur; friend class my_container; my_iterator( NodeType * ); // private constructor for begin, end }; typedef my_iterator< T, my_node< T > > iterator; typedef my_iterator< T const, my_node< T > const > const_iterator; 

वे अक्सर यह भूल जाते हैं कि iterator const_iterator कन्वर्ट करना चाहिए, लेकिन दूसरी तरह से नहीं। ऐसा करने का एक तरीका है:

 template<class T, class Tag = void> class IntrusiveSlistIterator : public std::iterator<std::forward_iterator_tag, T> { typedef SlistNode<Tag> Node; Node* node_; public: IntrusiveSlistIterator(Node* node); T& operator*() const; T* operator->() const; IntrusiveSlistIterator& operator++(); IntrusiveSlistIterator operator++(int); friend bool operator==(IntrusiveSlistIterator a, IntrusiveSlistIterator b); friend bool operator!=(IntrusiveSlistIterator a, IntrusiveSlistIterator b); // one way conversion: iterator -> const_iterator operator IntrusiveSlistIterator<T const, Tag>() const; }; 

उपरोक्त नोटिस में कैसे IntrusiveSlistIterator<T> IntrusiveSlistIterator<T const> लिए धर्मान्तरित IntrusiveSlistIterator<T const> यदि T पहले से ही इस रूपांतरण का इस्तेमाल करता है तो कभी भी इसका उपयोग नहीं किया जाता है

बहुत सारे अच्छे उत्तर हैं लेकिन मेरे पास एक टेम्पलेट हैडर है जो कि बहुत संक्षिप्त और उपयोग में आसान है।

अपने कक्षा में इटरेटर जोड़ने के लिए केवल छोटे वर्ग को 7 छोटी फ़ंक्शंस वाले इटरेटर की स्थिति का प्रतिनिधित्व करने के लिए आवश्यक है, जिनमें से 2 वैकल्पिक हैं:

 #include <iostream> #include <vector> #include "iterator_tpl.h" struct myClass { std::vector<float> vec; // Add some sane typedefs for STL compliance: STL_TYPEDEFS(float); struct it_state { int pos; inline void begin(const myClass* ref) { pos = 0; } inline void next(const myClass* ref) { ++pos; } inline void end(const myClass* ref) { pos = ref->vec.size(); } inline float& get(myClass* ref) { return ref->vec[pos]; } inline bool cmp(const it_state& s) const { return pos != s.pos; } // Optional to allow operator--() and reverse iterators: inline void prev(const myClass* ref) { --pos; } // Optional to allow `const_iterator`: inline const float& get(const myClass* ref) const { return ref->vec[pos]; } }; // Declare typedef ... iterator;, begin() and end() functions: SETUP_ITERATORS(myClass, float&, it_state); // Declare typedef ... reverse_iterator;, rbegin() and rend() functions: SETUP_REVERSE_ITERATORS(myClass, float&, it_state); }; 

फिर आप इसे इसका उपयोग कर सकते हैं जैसा कि आप एक एसटीएल इटरेटर से अपेक्षा करते हैं:

 int main() { myClass c1; c1.vec.push_back(1.0); c1.vec.push_back(2.0); c1.vec.push_back(3.0); std::cout << "iterator:" << std::endl; for (float& val : c1) { std::cout << val << " "; // 1.0 2.0 3.0 } std::cout << "reverse iterator:" << std::endl; for (auto it = c1.rbegin(); it != c1.rend(); ++it) { std::cout << *it << " "; // 3.0 2.0 1.0 } } 

मुझे उम्मीद है यह मदद करेगा।