Question

J'ai écrit une classe rare de vecteur (voir # 1 , # 2 .)

Je voudrais fournir deux types d'itérateurs:

Le premier ensemble, les itérateurs réguliers, peut pointer un élément quelconque, que ce soit ensemble ou à l'arrêt. S'ils sont lus, ils retournent soit la valeur de consigne ou value_type(), si elles sont écrites, ils créent l'élément et renvoyer la référence lvalue. Ainsi, ils sont:

Random Access Traversal Iterator et Lisible et inscriptibles Iterator

Le deuxième ensemble, les itérateurs rares, iterate que sur les éléments de réglage. Comme ils ne ont pas besoin de créer paresseusement des éléments qui sont écrits, ils sont:

Random Access Traversal Iterator et Lisible et inscriptibles et Lvalue Iterator

J'ai besoin aussi des versions const des deux, qui ne sont pas inscriptibles.

Je peux remplir les blancs, mais ne savez pas comment utiliser boost :: iterator_adaptor pour commencer.

Voici ce que j'ai à ce jour:

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

aussi, est-ce illégal?

typedef boost::reverse_iterator<sparse_iterator> reverse_sparse_iterator;
Était-ce utile?

La solution

Je ne suis pas sûr que vous voulez vraiment utiliser iterator_adaptor dans votre cas -. Vous pouvez utiliser à la place iterator_facade

Une explication plus approfondie: iterator_adaptors sont utilisés lorsque vous avez un itérateur existant (disons std::list<int>::iterator) et que vous souhaitez réutiliser son comportement pour votre iterator, par exemple. votre iterator retourne la valeur de ce qui est dans la liste, mais la réutilisation code traversal deux fois de la iterator originale. Ou l'inverse: vous voudrez peut-être un itérateur qui va sauter certains des éléments dans la liste initiale, mais le retour des valeurs inchangées. Je ne sais pas si vous voulez baser votre iterator (comme dans le code de réutilisation) sur itérateurs de vos structures sous-jacentes, mais parler pour moi, je ne serais pas en particulier dans le cas de iterator comme vous le feriez non faible souhaiterez probablement créer quelques-uns proxy pour la référence qui signifie que vous ne pouvez pas utiliser un sous-jacent iterator code dereference() et traversal est probablement facile. Vous pouvez, cependant, la base de votre sparse_iterator sur certains itérateur qui fait itère sur les éléments existants du tableau si vous voulez.

Il y a des problèmes avec l'approche proxy, donc ne vous attendez pas à travailler parfaitement sans passer par de nombreux cerceaux. D'une part, la version const du iterator doit retourner effectif non encore value_type(), qui expressions comme moyens iter->foo() devrait se traduire par value_type().foo() si l'entrée correspondante n'existe pas. Mais cela pose une difficulté, que pointer_proxy::operator->() doit retourner quelque chose avec operator->, de préférence un pointeur (certainement pas value_type()). Ce qui nous amène à la question cruciale: Un pointeur sur quoi? Il y a des possibilités pour résoudre ce (pour un, si vous avez vos objets gérés par boost::shared_pointer, vous pouvez simplement revenir un shared_pointer à une instance new'd).

Pour l'itérateur non faible, vous devez implémenter:

  • class reference_proxy avec
  • reference_proxy::operator& (qui renverra probablement un proxy pointeur)
  • reference_proxy::operator value_type&() pour des utilisations const
  • reference_proxy::operator const value_type&() pour des utilisations non-const
  • reference_proxy::foo() pour toute fonction de membre de foo() de value_type (autrement expressions comme (*it).foo() AFAIK ne fonctionnera pas)

  • class pointer_proxy avec

  • pointer_proxy::operator* (retourner un reference_proxy)
  • pointer_proxy::operator-> (faire quelque chose de sensé, voir ci-dessus)

Les paramètres au modèle de façade iterator devrait être:

  • Reference: le reference_proxy
  • Pointer: le pointer_proxy

La version clairsemée est plus simple: Si le sous-jacent iterator est sensible (.-À-dire correspond au comportement que vous voulez) et correctement mis en œuvre, vous pouvez simplement omettre les paramètres à la iterator_adaptor (sauf pour les deux premiers), et de prendre toute la mise en œuvre .

Le problème "ne compile pas". Insérer typename

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top