2010-05-12 15 views
11

मैं एक विरल वेक्टर वर्ग लिखा था (#1 देखते हैं, #2।)का उपयोग को बढ़ावा देने :: iterator

मैं iterators के दो प्रकार प्रदान करना चाहते हैं:

पहला सेट, नियमित रूप से iterators, किसी भी इंगित कर सकते हैं तत्व, सेट या अनसेट करें। यदि उन्हें पढ़ा जाता है, तो वे या तो सेट मान या value_type() लौटाते हैं, यदि वे लिखे गए हैं, तो वे तत्व बनाते हैं और lvalue संदर्भ लौटाते हैं। इस प्रकार, वे इस प्रकार हैं:

रैंडम एक्सेस Traversal इटरेटर और पठनीय और लिखने योग्य इटरेटर

दूसरे सेट, विरल iterators, से अधिक केवल सेट तत्वों पुनरावृति। चूंकि वे lazily तत्वों है कि करने के लिए लिखा जाता है बनाने के लिए की जरूरत नहीं है, वे हैं:

रैंडम एक्सेस Traversal इटरेटर और पठनीय और लिखने योग्य और lvalue इटरेटर

मैं भी स्थिरांक संस्करणों की आवश्यकता है दोनों, जो लिखने योग्य नहीं हैं।

मैं रिक्त स्थान भर सकता हूं, लेकिन यह सुनिश्चित नहीं कर सकता कि कैसे शुरू करने के लिए boost :: iterator_adaptor का उपयोग करें।

यहाँ मैं अब तक है:

template<typename T> 
class sparse_vector { 
public: 
    typedef size_t size_type; 
    typedef T value_type; 

private: 
    typedef T& true_reference; 
    typedef const T* const_pointer; 
    typedef sparse_vector<T> self_type; 
    struct ElementType { 
     ElementType(size_type i, T const& t): index(i), value(t) {} 
     ElementType(size_type i, T&& t): index(i), value(t) {} 
     ElementType(size_type i): index(i) {} 
     ElementType(ElementType const&) = default; 
     size_type index; 
     value_type value; 
    }; 
    typedef vector<ElementType> array_type; 

public: 
    typedef T* pointer; 
    typedef T& reference; 
    typedef const T& const_reference; 

private: 
    size_type         size_; 
    mutable typename array_type::size_type  sorted_filled_; 
    mutable array_type       data_; 

// lots of code for various algorithms... 

public:  
    class sparse_iterator 
     : public boost::iterator_adaptor< 
      sparse_iterator     // Derived 
      , typename array_type::iterator   // Base (the internal array) 
      , value_type    // Value 
      , boost::random_access_traversal_tag // CategoryOrTraversal 
      > {...} 

    class iterator_proxy { 
      ??? 
    }; 

    class iterator 
     : public boost::iterator_facade< 
      iterator       // Derived 
      , ?????       // Base 
      , ?????    // Value 
      , boost::?????? // CategoryOrTraversal 
      > { 
    }; 
}; 

भी, इस गैर कानूनी है?

typedef boost::reverse_iterator<sparse_iterator> reverse_sparse_iterator; 

उत्तर

19

मुझे यकीन है कि तुम सच में अपने मामले में iterator_adaptor उपयोग करना चाहते हैं नहीं कर रहा हूँ - आप के बजाय iterator_facade उपयोग करने के लिए चाहते हो सकता है।

अधिक संपूर्ण स्पष्टीकरण: iterator_adaptors का उपयोग तब किया जाता है जब आपके पास मौजूदा इटरेटर (चलिए std::list<int>::iterator कहें) और अपने इटरेटर के लिए इसके व्यवहार का पुन: उपयोग करना चाहते हैं, उदाहरण के लिए। आपका इटरेटर सूची में जो कुछ भी है, उसके मूल्य से दो गुना वापस आ जाएगा, लेकिन मूल पुनरावर्तक से ट्रैवर्सल कोड का पुन: उपयोग करें। या दूसरी तरफ: आप एक इटरेटर चाहते हैं जो मूल सूची में कुछ तत्वों को छोड़ देगा, लेकिन मानों को अपरिवर्तित वापस कर देगा। मुझे यकीन नहीं है कि क्या आप अपने अंतर्निहित संरचनाओं के इटरेटर पर अपने इटरेटर (जैसा कि पुन: उपयोग कोड में) का आधार बनाना चाहते हैं, लेकिन मेरे लिए बात करते हुए, मैं विशेष रूप से गैर-निवासी इटरेटर के मामले में नहीं होता क्योंकि आप शायद कुछ बनाना चाहते हैं संदर्भ के लिए प्रॉक्सी जिसका अर्थ है कि आप किसी अंतर्निहित इटरेटर dereference() कोड का उपयोग नहीं कर सकते हैं, और ट्रैवर्सल शायद आसान है। हालांकि, आप अपने sparse_iterator को कुछ इटरेटर पर आधार दे सकते हैं जो वास्तव में सरणी के मौजूदा तत्वों को फिर से सक्रिय करता है।

प्रॉक्सी दृष्टिकोण के साथ समस्याएं हैं, इसलिए उम्मीद है कि यह कई हुप्स के बिना बिना किसी काम के बेकार ढंग से काम करेगी। एक बात के लिए, nonsparse iterator का कॉन्स संस्करण अभी भी value_type() वापस करना चाहिए, जिसका अर्थ है कि iter->foo() जैसे अभिव्यक्तियों को value_type().foo() पर अनुवाद करना चाहिए यदि संबंधित प्रविष्टि मौजूद नहीं है। लेकिन यह एक कठिनाई है, pointer_proxy::operator->()operator-> के साथ कुछ वापस करना चाहिए, अधिमानतः एक सूचक (निश्चित रूप से value_type() नहीं)। जो महत्वपूर्ण सवाल की ओर जाता है: क्या एक सूचक?इस को हल करने के संभावनाएं हैं (एक के लिए, यदि आप अपने वस्तुओं boost::shared_pointer द्वारा प्रबंधित है, तो आप सिर्फ एक shared_pointer एक को new 'd उदाहरण दे सकें)।

nonsparse इटरेटर के लिए, आप लागू करने की आवश्यकता:

  • reference_proxy::operator& साथ
    • class reference_proxy (कि शायद एक सूचक प्रॉक्सी वापस आ जाएगी)
    • स्थिरांक के लिए reference_proxy::operator value_type&() का उपयोग करता
    • गैर स्थिरांक के लिए reference_proxy::operator const value_type&()
    • reference_proxy::foo() का उपयोग करता valu के किसी भी foo() सदस्य समारोह के लिए e_type (अन्यथा (*it).foo() AFAIK की तरह भाव से काम नहीं करेगा)

    • class pointer_proxy साथ

    • pointer_proxy::operator* (एक reference_proxy वापसी)
    • pointer_proxy::operator-> (कुछ समझदार करते हैं, ऊपर देखें)

    मापदंडों के इटेटरेटर मुखौटा टेम्पलेट होना चाहिए:

    • Reference: reference_proxy
    • Pointer: pointer_proxy

    विरल संस्करण सरल है: है कि अंतर्निहित इटरेटर समझदार है (यानी। व्यवहार आप चाहते हैं मेल खाता है) और ठीक से लागू, तो आप सिर्फ iterator_adaptor के मापदंडों को छोड़ सकते हैं (पहले दो को छोड़ कर), और सभी कार्यान्वयन ले।

    "संकलन नहीं है" समस्या: typename डालें।

  • +0

    हाँ, मुझे लगता है कि आप एक इटरेटर के लिए सही हैं ... मैंने सवाल अपडेट किया है। –

    +0

    क्या आप का वर्णन कर रहे हैं वास्तव में मैं क्या चाहते है, हाँ। –

    +0

    मैं इसे कई बार कैसे बढ़ा सकता हूं? :) –

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