मेरे अपने Iterators बनाना


141

मैं C ++ सीखने की कोशिश कर रहा हूं, इसलिए मुझे क्षमा करें यदि यह प्रश्न बुनियादी ज्ञान की कमी को प्रदर्शित करता है, तो आप देखें, तथ्य यह है, मेरे पास बुनियादी ज्ञान की कमी है।

मैं कुछ मदद करना चाहता हूं जो मैंने बनाई कक्षा के लिए एक पुनरावृत्ति बनाने के लिए काम कर रहा है।

मेरे पास एक क्लास 'शेप' है जिसमें पॉइंट्स का एक कंटेनर है। मेरे पास एक वर्ग 'टुकड़ा' है जो एक आकृति को संदर्भित करता है और आकृति के लिए एक स्थिति को परिभाषित करता है। टुकड़ा एक आकार नहीं है यह सिर्फ एक आकृति का संदर्भ देता है।

मैं चाहता हूं कि ऐसा लगता है कि टुकड़ा अंकों का एक कंटेनर है जो आकृति के समान हैं जो इसे संदर्भित करते हैं लेकिन टुकड़े की स्थिति की भरपाई के साथ।

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


6
नमूना कोड को पोस्ट करने से यह वर्णन करने में मदद मिलेगी कि आप सादे अंग्रेजी पाठ से बेहतर क्या कर रहे हैं।
ग्रेग रोजर्स

3
कस्टम पुनरावृत्तियों का निर्माण शायद एक मूल शीर्ष नहीं है, कम से कम मध्यवर्ती।
ldog

जवाबों:


41

आपको Boost.Iterators का उपयोग करना चाहिए। इसमें नए पुनरावृत्तियों और मौजूदा पुनरावृत्तियों के लिए एडेप्टर को लागू करने के लिए कई टेम्पलेट और अवधारणाएं शामिल हैं। मैंने इस विषय पर एक लेख लिखा है ; यह दिसंबर 2008 ACCU पत्रिका में है। यह आपकी समस्या के लिए एक (IMO) सुरुचिपूर्ण समाधान पर चर्चा करता है: Boost.Iterators का उपयोग करके किसी ऑब्जेक्ट से सदस्य संग्रह को उजागर करना।

यदि आप केवल एसटीएल का उपयोग करना चाहते हैं, तो जोसैटिस पुस्तक में आपके स्वयं के एसटीएल पुनरावृत्तियों को लागू करने पर एक अध्याय है।


3
बस एक छोटी सी टिप्पणी: पुस्तक सी ++ मानक पुस्तकालय के बारे में बोलती है, एसटीएल नहीं - ये अलग-अलग हैं, लेकिन बहुत भ्रमित हो जाते हैं (मैं दोषी हूं / बहुत दोषी था)
CppChris

62

/ संपादित करें: मैं देख रहा हूँ, एक इटरेटर वास्तव में यहाँ आवश्यक है (मैंने पहले प्रश्न को गलत बताया)। फिर भी, मैं नीचे दिए गए कोड को स्टैंड दे रहा हूं क्योंकि यह समान परिस्थितियों में उपयोगी हो सकता है।


क्या वास्तव में स्वयं का पुनरावृत्ति आवश्यक है? शायद यह वास्तविक अंक रखने वाले कंटेनर के लिए सभी आवश्यक परिभाषाओं को अग्रेषित करने के लिए पर्याप्त है:

// Your class `Piece`
class Piece {
private:
    Shape m_shape;

public:

    typedef std::vector<Point>::iterator iterator;
    typedef std::vector<Point>::const_iterator const_iterator;

    iterator begin() { return m_shape.container.begin(); }

    const_iterator begin() const { return m_shape.container.begin(); }

    iterator end() { return m_shape.container.end(); }

    const_iterator end() const { return m_shape.const_container.end(); }
}

यह मान रहा है कि आप vectorआंतरिक रूप से उपयोग कर रहे हैं, लेकिन प्रकार आसानी से अनुकूलित किया जा सकता है।


शायद वह अपनी कक्षा के खिलाफ एसटीएल एल्गोरिथ्म या कार्यात्मक सुविधाओं का उपयोग करना चाहता है ...
gbjbaanb

2
मूल प्रश्न वास्तव में कहता है कि टुकड़ा कंटेनर के पुनरावृत्तिकर्ता को उन्हें वापस करते समय मूल्यों को संशोधित करना चाहिए। इसके लिए एक अलग पुनरावृत्तिकर्ता की आवश्यकता होगी, हालांकि यह संभवतः विरासत में मिला होना चाहिए या अन्यथा मूल से प्राप्त किया जाना चाहिए।
वर्कमैड 3

@ जीबीजैनब: मेरे कोड के बारे में अच्छी बात यह है कि इसका उपयोग एसटीएल एल्गोरिदम द्वारा किया जा सकता है।
कोनराड रुडोल्फ

1
कुछ वर्षों बाद और यह अभी भी Google पर शीर्ष परिणामों में से है ... अब इस तरह से कुछ करके इसे सामान्यीकृत करना संभव है:auto begin() -> decltype(m_shape.container.begin()) { return m_shape.container.begin(); }
user2962533

20

यहां कस्टम कंटेनर की तरह एक एसटीएल डिजाइन करना एक उत्कृष्ट लेख है जो कुछ बुनियादी अवधारणाओं को बताता है कि कैसे एसटीएल जैसे कंटेनर वर्ग को इसके लिए पुनरावृत्ति वर्ग के साथ डिजाइन किया जा सकता है। रिवर्स इटरेटर (थोड़ा मुश्किल) हालांकि एक अभ्यास के रूप में छोड़ दिया जाता है :-)

HTH,



2

C ++ में कस्टम पुनरावृत्तियों को लिखना समझने के लिए काफी क्रियात्मक और जटिल हो सकता है।

चूँकि मुझे कस्टम इटैलर लिखने का न्यूनतम तरीका नहीं मिला, इसलिए मैंने यह टेम्प्लेट हेडर लिखा जो मदद कर सकता है। उदाहरण के लिए, Pieceवर्ग को चलने योग्य बनाने के लिए :

#include <iostream>
#include <vector>

#include "iterator_tpl.h"

struct Point {
  int x;
  int y;
  Point() {}
  Point(int x, int y) : x(x), y(y) {}
  Point operator+(Point other) const {
    other.x += x;
    other.y += y;
    return other;
  }
};

struct Shape {
  std::vector<Point> vec;
};

struct Piece {
  Shape& shape;
  Point offset;
  Piece(Shape& shape, int x, int y) : shape(shape), offset(x,y) {}

  struct it_state {
    int pos;
    inline void next(const Piece* ref) { ++pos; }
    inline void begin(const Piece* ref) { pos = 0; }
    inline void end(const Piece* ref) { pos = ref->shape.vec.size(); }
    inline Point get(Piece* ref) { return ref->offset + ref->shape.vec[pos]; }
    inline bool cmp(const it_state& s) const { return pos != s.pos; }
  };
  SETUP_ITERATORS(Piece, Point, it_state);
};

तब आप इसे एक सामान्य एसटीएल कंटेनर के रूप में उपयोग करने में सक्षम होंगे:

int main() {
  Shape shape;
  shape.vec.emplace_back(1,2);
  shape.vec.emplace_back(2,3);
  shape.vec.emplace_back(3,4);

  Piece piece(shape, 1, 1);

  for (Point p : piece) {
    std::cout << p.x << " " << p.y << std::endl;
    // Output:
    // 2 3
    // 3 4
    // 4 5
  }

  return 0;
}

यह अन्य प्रकार के पुनरावृत्तियों को जोड़ने की अनुमति देता है जैसे const_iteratorया reverse_const_iterator

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


1

आपकी समस्या का समाधान आपके स्वयं के पुनरावृत्तियों का निर्माण नहीं है, बल्कि मौजूदा एसटीएल कंटेनरों और पुनरावृत्तियों का उपयोग है। वेक्टर की तरह एक कंटेनर में प्रत्येक आकार में अंक स्टोर करें।

class Shape {
    private:
    vector <Point> points;

आप तब से क्या करते हैं, यह आपके डिजाइन पर निर्भर करता है। सबसे अच्छा तरीका है शेप के अंदर के तरीकों में अंकों के माध्यम से पुनरावृति करना।

for (vector <Point>::iterator i = points.begin(); i != points.end(); ++i)
    /* ... */

यदि आपको आकार के बाहर के बिंदुओं तक पहुँचने की आवश्यकता है (यह एक कमी वाले डिजाइन का चिह्न हो सकता है) तो आप आकृति विधियों में बना सकते हैं जो बिंदुओं के लिए पुनरावृत्त अभिगम कार्यों को लौटाएंगे (उस स्थिति में अंक कंटेनर के लिए एक सार्वजनिक टाइपफ़ीड भी बनाएं)। इस दृष्टिकोण के विवरण के लिए कोनराड रूडोल्फ द्वारा जवाब देखें।


3
उसे अभी भी अपना इटैलर बनाने की आवश्यकता होगी जो कि उस टुकड़े में दिए गए आकृतियों के टुकड़े का अनुरोध करता है। कस्टम पुनरावृत्तियों यहाँ एक महान उपकरण हैं, और उपयोग करने के लिए बहुत ही सुंदर हैं।
Roel
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.