باستخدام Boost :: iterator
-
26-09-2019 - |
سؤال
كتبت فئة متجه ضار (انظر #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
.