2010-05-12 10 views
11

I (., #1 bakınız #2)kullanma boost :: yineleyici

Ben Yineleyicilerin iki çeşit sağlamak istiyorum seyrek vektör sınıfı yazdı eleman, set olsun ya da unset. Bunlar okunduğunda, ayarlanan değeri veya value_type() değerini döndürürler, eğer bunlar yazılırsa öğeyi oluşturur ve lvalue başvurusunu döndürür. Böylece onlar:

Rasgele Erişim Geçişi Yineleyici ve Okunabilir ve Yazılabilir Yineleyici

ikinci seti, seyrek yineleyiciler, üzerinde sadece set elemanları yineleme. onlar tembel yazılır öğeleri oluşturmak gerek olmadığından, onlar:

Rasgele Erişim Geçişi Yineleyici ve Okunabilir ve Yazılabilir ve lvalue Yineleyici Ben de const versiyonlarını ihtiyaç

Her ikisi de, yazılabilir değil.

Boşlukları doldurabilirim, ancak başlamak için boost :: iterator_adaptor'u nasıl kullanacağınızdan emin değilim. Bu yasadışı, ayrıca

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 
      > { 
    }; 
}; 

: Burada

Ben bugüne kadar ne var? Ben gerçekten durumunda iterator_adaptor kullanmak istediğiniz emin değilim

typedef boost::reverse_iterator<sparse_iterator> reverse_sparse_iterator; 

cevap

19

- yerine iterator_facade kullanmak isteyebilirsiniz.

Daha ayrıntılı bir açıklama: iterator_adaptors, mevcut bir yineleyiciniz olduğunda (std::list<int>::iterator diyelim) ve yineleyiciniz için davranışını yeniden kullanmak istediğinizde kullanılır. Yineleyiciniz listedeki değerin iki katı değerine döner, ancak orijinal kodlayıcıdan geçiş kodunu yeniden kullanır. Ya da başka bir şekilde: orijinal listedeki öğelerin bazılarını atlayacak bir yineleyici isteyebilirsiniz, ancak değerleri değişmeden döndürebilirsiniz. Alttaki yapıların yineleyicileri üzerinde yineleyicinizi (yeniden kullanım kodunda olduğu gibi) temel almak isteyip istemediğinizden emin değilim, ama benim için konuşmam gerekirse, özellikle bazılarını oluşturmak isteyeceğiniz gibi, nonsparse yineleyici durumunda olmazdım. referans için vekil herhangi bir temel yineleyici kullanamazsınız anlamına gelir dereference() kodu ve geçiş muhtemelen kolay. Bununla birlikte, sparse_iterator'unuzu, isterseniz dizinin gerçekten var olan öğeleri üzerinde yinelenen bazı yineleyicilerde temel alabilirsiniz.

Vekil yaklaşımıyla ilgili sorunlar var, bu nedenle çok sayıda kasnaktan geçmeden kusursuz çalışmasını beklemeyin. Bir şey için, nonsparse yineleyicinin const sürümü hala value_type()'u döndürmelidir; bu, karşılık gelen giriş mevcut değilse iter->foo() gibi ifadelerin value_type().foo()'a çevrilmesi gerektiği anlamına gelir. Ancak bu, pointer_proxy::operator->()'un operator->, tercihen bir işaretçi (kesinlikle value_type() değil) ile bir şey döndürmesi gereken bir zorluk teşkil etmektedir. Hangi önemli soruya yol açar: Ne için bir işaretçi?Bunu çözmenin olasılıklar (biri için boost::shared_pointer tarafından yönetilen nesneler varsa, sadece bir shared_pointer kalsa hepsini new a örneğini dönebilir) vardır. Kat Karşılığı

  • reference_proxy::operator value_type&() dışı Kat Karşılığı
  • reference_proxy::operator const value_type&() kullanır (muhtemelen bir işaretçi vekil dönecektir)

    • class reference_proxy
    • reference_proxy::operator& ile: nonsparse yineleyici için

      , uygulamak gerekir valu herhangi foo() üyesi işlev için
    • reference_proxy::foo() kullanır e_type (Aksi (*it).foo() afaik gibi ifadeler çalışmaz)

    • class pointer_proxy ile

    • pointer_proxy::operator* (return bir reference_proxy)
    • pointer_proxy::operator-> (mantıklı bir şey yapmak yukarıya bakınız)

    parametrelerini yineleyici cephe şablonu olmalıdır:

    • Reference: reference_proxy
    • Pointer: pointer_proxy

    seyrek versiyonu daha basittir: altta yatan yineleyici (yani mantıklı ise. istediğiniz davranışı eşleştirir) ve düzgün bir şekilde uygulandığında, parametreleri iterator_adaptor'a (ilk ikisi hariç) atlayabilir ve tüm uygulamayı gerçekleştirebilirsiniz.

    "derleme değil" sorun: typename yerleştirin.

  • +0

    evet, ben soruyu güncelledik ... Eğer Yineleyicilerin biri için haklısın. –

    +0

    anlattığın şey tam olarak istediğim şey, evet. –

    +0

    Bunu birden çok kez nasıl destekleyebilirim? :) –