سؤال

كتبت فئة متجه ضار (انظر #1, #2.)

أود أن أقدم نوعين من المتكررين:

يمكن للمجموعة الأولى ، المترجمين العاديين ، توجيه أي عنصر ، سواء تم تعيينه أو إلغاء ضبطه. إذا تمت قراءتهم ، فإنهم يعيدون إما القيمة المحددة أو value_type(), ، إذا تمت كتابتها ، فإنهم يقومون بإنشاء العنصر وإرجاع مرجع LVALUE. وهكذا ، هم:

التكرار العشوائي للوصول و قابلة للقراءة و قابل للكتابة التكرار

المجموعة الثانية ، المتكررون المتفرقون ، يتكررون فقط على العناصر المحددة. نظرًا لأنهم لا يحتاجون إلى إنشاء عناصر مكتوبة عليها ، فهي:

التكرار العشوائي للوصول و قابلة للقراءة و قابل للكتابة و Lvalue التكرار

أحتاج أيضًا إلى إصدارات const من كليهما ، والتي لا يمكن كتابتها.

يمكنني ملء الفراغات ، ولكن لست متأكدًا من كيفية استخدام 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;
هل كانت مفيدة؟

المحلول

لست متأكدًا أنك تريد حقًا استخدامها iterator_adaptor في حالتك - قد ترغب في استخدامها iterator_facade في حين أن.

تفسير أكثر شمولية: iterator_adaptors يتم استخدامها عندما يكون لديك مؤلف موجود (دعنا نقول std::list<int>::iterator) وترغب في إعادة استخدام سلوكها لمؤلفك ، على سبيل المثال. سيعيد التكرار مرتين قيمة ما هو موجود في القائمة ، ولكن إعادة استخدام رمز اجتياز من جهاز ITerator الأصلي. أو العكس: قد ترغب في التكرار الذي سيتخطى بعض العناصر في القائمة الأصلية ، ولكن إرجاع القيم دون تغيير. لست متأكدًا مما إذا كنت تريد أن تبني التكرار الخاص بك (كما هو الحال في رمز إعادة الاستخدام) على تكراري الهياكل الأساسية الخاصة بك ، لكن التحدث عني ، لن أفعل بشكل خاص في حالة التكرار غير اللذيذ كما تريد إنشاء بعض وكيل للمرجع مما يعني أنه لا يمكنك استخدام أي تكرار أساسي dereference() الرمز ، وربما يكون اجتياز سهلة. يمكنك ، ومع ذلك ، أن تبني الخاص بك sparse_iterator على بعض التكرار الذي يكرر عن عناصر الصفيف الموجودة بالفعل إذا كنت تريد.

هناك مشاكل في نهج الوكيل ، لذلك لا تتوقع أن تعمل بلا عيب دون أن تمر بالعديد من الأطواق. لسبب واحد ، لا يزال يتعين على نسخة const من التكرار غير اللامع العودة value_type(), مما يعني تعبيرات مثل iter->foo() يجب أن تترجم إلى value_type().foo() إذا لم يكن الإدخال المقابل موجودًا. لكن هذا يشكل صعوبة pointer_proxy::operator->() يجب أن تعيد شيء مع operator->, ويفضل أن يكون مؤشرًا (بالتأكيد لا value_type()). الذي يؤدي إلى السؤال الحاسم: مؤشر على ماذا؟ هناك إمكانيات لحل هذا (من أجل واحد ، إذا كان لديك كائناتك التي تمت إدارتها بواسطة boost::shared_pointer, ، يمكنك فقط إعادة أ shared_pointer إلى newمثيل د).

من أجل ايتراتور غير اللصوص ، تحتاج إلى تنفيذ:

  • class reference_proxy مع
  • reference_proxy::operator& (من المحتمل أن يعيد وكيل مؤشر)
  • reference_proxy::operator value_type&() لاستخدامات كونست
  • reference_proxy::operator const value_type&() للاستخدامات غير الممتدة
  • reference_proxy::foo() لأي foo() وظيفة العضو في value_type (خلاف ذلك تعبيرات مثل (*it).foo() لن يعمل AFAIK)

  • class pointer_proxy مع

  • pointer_proxy::operator* (إرجاع مرجع _proxy)
  • pointer_proxy::operator-> (افعل شيئًا معقولًا ، انظر أعلاه)

يجب أن تكون المعلمات إلى قالب واجهة التكرار:

  • Reference: ال reference_proxy
  • Pointer: ال pointer_proxy

الإصدار المتفرق أبسط: إذا كان التكرار الأساسي معقولًا (أي. يطابق السلوك الذي تريده) وتنفيذه بشكل صحيح ، يمكنك فقط حذف المعلمات إلى iterator_adaptor (باستثناء الأولين) ، واتخذ كل التنفيذ.

مشكلة "لا تجمع": أدخل typename.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top