কাস্টম পুনরাবৃত্তকারী এবং কনস্টিটারগুলি সঠিকভাবে প্রয়োগ করবেন?


240

আমি একটি কাস্টম ধারক বর্গ যার জন্য আমি লিখতে চাই আছে iteratorএবং const_iteratorক্লাস।

আমি এর আগে কখনও এটি করিনি এবং আমি কীভাবে উপযুক্ত তা খুঁজে পেতে ব্যর্থ হয়েছি। পুনরুক্তি তৈরি সম্পর্কিত নির্দেশিকা কী কী এবং আমার কী সম্পর্কে সচেতন হওয়া উচিত?

আমি কোড সদৃশতা এড়াতেও চাই (আমি এটি অনুভব করি) const_iterator এবং iteratorঅনেকগুলি ভাগ ; একজনের কি অন্যটি সাবক্লাস করা উচিত?)।

পাদটীকা: আমি নিশ্চিত যে বুস্টের এটিকে স্বাচ্ছন্দ্য দেওয়ার জন্য কিছু আছে তবে আমি এখানে এটি ব্যবহার করতে পারছি না, অনেক বোকা কারণে।



জিওএফ ইটারেটর প্যাটার্নটি কি আদৌ বিবেচনা করা হচ্ছে?
ডাম্বকোডার

3
@ ডাম্ব কোডার: সি ++ এ এটির পুনরাবৃত্তকারীগুলি এসটিএল-কমপ্লায়েন্ট হওয়া প্রায়শই কাম্য। ধারণাটি সমান হলেও, জিওএফ প্রস্তাবিত প্যাটার্নে কিছু পার্থক্য রয়েছে।
বুর্জন ​​পোলেক্স


1
এই উত্তরগুলির জটিলতা থেকে বোঝা যায় যে সি ++ হ'ল একটি ভাষা হ'ল আপ-জাম্পযুক্ত আন্ডারগ্র্যাডগুলির জন্য হোমওয়ার্ক অ্যাসাইনমেন্ট ছাড়া অন্য কোনও কিছুর জন্য অযোগ্য, বা উত্তরগুলি অত্যধিক জটিল এবং ভুল। সিপিপিতে অবশ্যই একটি সহজ উপায় থাকতে হবে? সিএমকে এবং অটোমাকে তৈরি করার আগে এটির মতো, কাঁচা সি একটি অজগর প্রোটোটাইপের বাইরে সিদ্ধ করা এর থেকে অনেক সহজ বলে মনে হয়।
ক্রিস্টোফার

উত্তর:


157
  • আপনার ধারককে ফিট করে এমন ধরণের পুনরাবৃত্তি চয়ন করুন: ইনপুট, আউটপুট, ফরোয়ার্ড ইত্যাদি fits
  • স্ট্যান্ডার্ড লাইব্রেরি থেকে বেস পুনরাবৃত্তি ক্লাস ব্যবহার করুন। উদাহরণস্বরূপ, std::iteratorসঙ্গে random_access_iterator_tag.These বেস ক্লাস এবং সব ধরনের Stl দ্বারা প্রয়োজনীয় সংজ্ঞা নির্ধারণ অন্যান্য কাজ না।
  • কোড সদৃশতা এড়ানোর জন্য ক্লাসটি একটি টেম্পলেট শ্রেণি হওয়া উচিত এবং "মান ধরণ", "পয়েন্টার টাইপ", "রেফারেন্স টাইপ" বা তাদের সমস্ত (প্রয়োগের উপর নির্ভর করে) দ্বারা প্যারামিটারাইজ করা উচিত। উদাহরণ স্বরূপ:

    // 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টাইপ সংজ্ঞা: এগুলি আপনার অ-কনস্ট্যান্ড এবং কনস্টের পুনরাবৃত্তিকারীদের জন্য প্রকার।

আরও দেখুন: স্ট্যান্ডার্ড লাইব্রেরি রেফারেন্স

সম্পাদনা: std::iterator সি ++ 17 সাল থেকে অবহেলা করা হয়েছে। এখানে সম্পর্কিত সম্পর্কিত আলোচনা দেখুন ।


8
@ পোটাটোসওয়াতর: এটিকে কমানো হয়নি, তবে ওহে, random_access_iteratorমানদণ্ডে নেই এবং উত্তরটি পরিবর্তনীয় থেকে কনস্ট রূপান্তরকে পরিচালনা করে না। আপনি সম্ভবত উত্তরাধিকারী হতে চান, std::iterator<random_access_iterator_tag, value_type, ... optional arguments ...>যদিও।
ইয়াকভ গালকা

2
হ্যাঁ, আমি কীভাবে এটি কাজ করে তা পুরোপুরি নিশ্চিত নই। আমার যদি পদ্ধতিটি থাকে তবে RefType operator*() { ... }আমি এক ধাপ কাছাকাছি - তবে এটি সাহায্য করে না, কারণ আমার এখনও দরকার RefType operator*() const { ... }
অটোমল্টস



5
যদি এটি অবচয় হয় তবে এর পরিবর্তে সঠিক "নতুন" উপায়টি কী?
সাসকিউ

56

আমি আপনাকে দেখিয়ে যাচ্ছি যে কীভাবে আপনি সহজেই আপনার কাস্টম ধারকগুলির জন্য পুনরাবৃত্তির সংজ্ঞা দিতে পারেন, তবে কেবলমাত্র আমি একটি সি ++ 11 লাইব্রেরি তৈরি করেছি যা আপনাকে সহজেই কোনও ধরণের ধারক, স্বতন্ত্র বা কাস্টম আচরণের সাথে কাস্টম আউটরেটর তৈরি করতে দেয় or অ সংলগ্ন।

আপনি গিথুব এ এটি পেতে পারেন

কাস্টম পুনরাবৃত্তকারী তৈরি এবং ব্যবহারের জন্য সহজ পদক্ষেপ এখানে:

  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:
    
        using iterator_category = std::random_access_iterator_tag;
        using value_type = blDataType;
        using difference_type = std::ptrdiff_t;
        using pointer = blDataType*;
        using reference = 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 difference_type& movement){m_ptr += movement;return (*this);}
        blRawIterator<blDataType>&                  operator-=(const difference_type& movement){m_ptr -= movement;return (*this);}
        blRawIterator<blDataType>&                  operator++(){++m_ptr;return (*this);}
        blRawIterator<blDataType>&                  operator--(){--m_ptr;return (*this);}
        blRawIterator<blDataType>                   operator++(int){auto temp(*this);++m_ptr;return temp;}
        blRawIterator<blDataType>                   operator--(int){auto temp(*this);--m_ptr;return temp;}
        blRawIterator<blDataType>                   operator+(const difference_type& movement){auto oldPtr = m_ptr;m_ptr+=movement;auto temp(*this);m_ptr = oldPtr;return temp;}
        blRawIterator<blDataType>                   operator-(const difference_type& movement){auto oldPtr = m_ptr;m_ptr-=movement;auto temp(*this);m_ptr = oldPtr;return temp;}
    
        difference_type                             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 difference_type& movement){this->m_ptr -= movement;return (*this);}
        blRawReverseIterator<blDataType>&           operator-=(const difference_type& 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++(int){auto temp(*this);--this->m_ptr;return temp;}
        blRawReverseIterator<blDataType>            operator--(int){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;}
    
        difference_type                             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]);}

                            .
                            .
                            .
    // This is the pointer to the
    // beginning of the data
    // This allows the container
    // to either "view" data owned
    // by other containers or to
    // own its own data
    // You would implement a "create"
    // method for owning the data
    // and a "wrap" method for viewing
    // data owned by other containers

    blDataType*                                    m_data;
};

আমি মনে করি অপারেটর + এবং অপারেটর- এর অপারেশনগুলি পিছনের দিকে থাকতে পারে। দেখে মনে হচ্ছে অপারেটর + পয়েন্টারটি যোগ না করে অপারেটর থেকে চলাচল বিয়োগ করছে - এটি যুক্ত করছে। এই পিছন বলে মনে হয়
beached

এটি বিপরীত পুনরুক্তির জন্য, অপারেটর + এর পিছনের দিকে যেতে হবে এবং অপারেটরটি এগিয়ে যেতে হবে
Enzo

2
অসাধারণ. গৃহীত উত্তরটি খুব উচ্চ স্তরের। এটা সত্যিই দারুন. ধন্যবাদ এনজো।
ফার্নান্দোজেড

আপনার নিজের উত্তরটি সম্পাদনা করতে হবে। ধরে নিই যে m_data বরাদ্দ হয়েছিল m_size উপাদানগুলির সাথে আপনি অপরিজ্ঞাত আচরণ পান: m_data[m_size]এটি ইউবি। আপনি কেবল এটির সাথে প্রতিস্থাপন করে এটি ঠিক করতে পারেন m_data+m_size। বিপরীত পুনরাবৃত্তকারীদের জন্য m_data[-1]এবং উভয়ই m_data-1ভুল (ইউবি)। রিভার্স_িটরেটরগুলি ঠিক করতে আপনার "পরবর্তী উপাদানগুলির কৌশলতে পয়েন্টার" ব্যবহার করতে হবে।
আরনৌড

আরনাউড, আমি কেবলমাত্র কাস্টম ধারক শ্রেণিতে পয়েন্টার সদস্যকে যুক্ত করেছি যা আমি বলতে চাইছি তা আরও ভাল করে দেখায়।
এনজো

24

তারা প্রায়শই ভুলে যায় যে 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>। যদি Tইতিমধ্যে হয় তবে constএই রূপান্তরটি কখনই ব্যবহৃত হয় না।


প্রকৃতপক্ষে, আপনি টেমপ্লেটযুক্ত একটি অনুলিপি নির্ধারককে সংজ্ঞায়িত করে অন্য উপায়ে এটিও করতে পারেন, আপনি যদি অন্তর্নিহিত প্রকারটি constনন- এ কাস্ট করার চেষ্টা করেন তবে এটি সংকলন করবে না const
ম্যাথিউ এম।

আপনি কি কোনও অবৈধের সাথে শেষ করবেন না IntrusiveSlistIterator<T const, void>::operator IntrusiveSlistIterator<T const, void>() const?
পোটোসওয়টার

আহ, এটি বৈধ, তবে কমাউ একটি সতর্কতা দেয় এবং আমি সন্দেহ করি যে আরও অনেক লোকও তা করবে। একটি enable_ifএটি ঠিক করতে পারে, তবে ...
পটোটোওয়াত্টার

আমি সক্ষম_আইফের সাথে বিরক্ত করিনি কারণ সংকলক যেভাবেই এটি অক্ষম করে, যদিও কিছু সংকলক একটি সতর্কতা দেয় (জি ++ ভাল ছেলে হওয়ার কারণে সতর্ক করা হয় না)।
ম্যাক্সিম এগারুশকিন

1
@ ম্যাথিউ: যদি কেউ টেমপ্লেট কনস্ট্রাক্টরের সাথে যান, কনস্টাইলারকে কনটাইলার পুনরায় রূপান্তর করার সময় কম্পাইলারটি কনস্ট্রাক্টরের ভিতরে একটি ত্রুটি তৈরি করে, যাতে ব্যবহারকারী তার মাথাটি বিভ্রান্তিতে ফেলে দেয় এবং ডাব্লুটিএফএফ করে দেয়। রূপান্তরকারী অপারেটরটির সাথে আমি পোস্ট করেছি, সংকলকটি কেবলমাত্র বলেছে যে কনস্ট_াইটেটর থেকে পুনরাবৃত্তিতে কোনও উপযুক্ত রূপান্তর নেই, যা আইএমও, আরও স্পষ্ট।
ম্যাক্সিম এগারুশকিন

23

বুস্টের সাহায্যের জন্য কিছু রয়েছে: বুস্ট.আইট্রেটর লাইব্রেরি।

আরও সুনির্দিষ্টভাবে এই পৃষ্ঠাটি: বুস্ট :: পুনরুদ্ধারকারী_আডাপ্টর

সবচেয়ে আকর্ষণীয়টি হল টিউটোরিয়াল উদাহরণ যা একটি কাস্টম ধরণের জন্য স্ক্র্যাচ থেকে সম্পূর্ণ বাস্তবায়ন দেখায়।

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এটি।


আপনি এই মন্তব্যটির অর্থ ব্যাখ্যা করতে পারেন? // a private type avoids misuse
কেভিনার্পে

@ কেভিনার্প: enablerকখনই কলকারী সরবরাহকারী হওয়ার উদ্দেশ্যে নয়, তাই আমার ধারণা হ'ল লোকেরা দুর্ঘটনাক্রমে এটি পাস করার চেষ্টা এড়াতে এটিকে ব্যক্তিগত করে তোলে। আমি মনে করি না যে, এটি আসলে এটি পাস করার জন্য কোনও সমস্যা তৈরি করতে পারে, যেহেতু সুরক্ষা রয়েছে enable_if
ম্যাথিউ এম।

16

আমি জানি না বুস্টের এমন কিছু আছে যা সাহায্য করবে।

আমার পছন্দসই প্যাটার্নটি সহজ: একটি টেম্পলেট যুক্তি নিন যা সমান 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;

দ্রষ্টব্য: দেখে মনে হচ্ছে আপনার রূপান্তরগুলি পুনরাবৃত্তকারী-> কনস্ট_টিরেটর এবং পিছনে ভাঙ্গা রয়েছে।
ম্যাক্সিম এগারুশকিন

@ ম্যাক্সিম: হ্যাঁ, আমি আমার প্রযুক্তিটি ব্যবহার করার কোনও উদাহরণ খুঁজে পাচ্ছি না: ভিপি। আমি নিশ্চিত না আপনি কী বোঝাতে চেয়েছেন তা রূপান্তরগুলি নষ্ট হয়েছে, যেহেতু আমি কেবল তাদের চিত্রিত করি নি, তবে curবিপরীত দৃ const়তার পুনরাবৃত্তিকারীদের কাছ থেকে অ্যাক্সেস করার ক্ষেত্রে কোনও সমস্যা হতে পারে । যে সমাধানটি মনে আসে তা হ'ল friend my_container::const_iterator; friend my_container::iterator;, তবে আমি মনে করি না যে আমি আগে এটি কীভাবে করেছি… যাইহোক এই সাধারণ রূপরেখাটি কাজ করে।
পোটোসওয়টার

1
* এটি friend classউভয় ক্ষেত্রেই করুন।
পোটোসওয়টার

এটি কিছু সময় হয়ে গেছে, তবে আমি এখনই স্মরণ করছি যে অন্তর্নিহিত সদস্য সূচনাটির সু-গঠনের উপর রূপান্তরগুলি পূর্বাভাস দেওয়া উচিত (SFINAE দ্বারা)। এটি SCARY প্যাটার্ন অনুসরণ করে (তবে এই পোস্টটি সেই পরিভাষাটির পূর্বাভাস দেয়)।
পোটোটোওয়াতর

13

প্রচুর ভাল উত্তর আছে তবে আমি একটি টেম্পলেট শিরোনাম তৈরি করেছি আমি ব্যবহার করি এমন করেছি যা যথেষ্ট সংক্ষিপ্ত এবং ব্যবহারযোগ্য।

আপনার শ্রেণিতে একটি পুনরাবৃত্তকারী যুক্ত করতে কেবল 7 টি ছোট ফাংশন সহ পুনরাবৃত্তির অবস্থার প্রতিনিধিত্ব করার জন্য একটি ছোট শ্রেণি লিখতে হবে, যার মধ্যে 2 টি areচ্ছিক:

#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
  }
}

আমি আসা করি এটা সাহায্য করবে.


1
এই টেমপ্লেট ফাইলটি আমার পুনরাবৃত্তির সমস্ত সমস্যার সমাধান করেছে!
পেরিকিপিকারি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.