IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Boost C++ Discussion :

boost::iterator_adaptor : instantiation


Sujet :

Boost C++

Vue hybride

ehmicky boost::iterator_adaptor :... 16/10/2011, 21h12
ehmicky Problème 1 résolu :... 20/10/2011, 12h11
Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Août 2007
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 39
    Par défaut boost::iterator_adaptor : instantiation
    Bonjour !

    J'essaie d'utiliser boost::iterator_adaptor, mais j'ai quelques soucis.
    Mon premier problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include    <boost/iterator_adaptors.hpp>
    #include    <algorithm>
    #include    <iostream>
     
    template <class T>
    class Reverse : public boost::iterator_adaptor <Reverse<T>, T> 
    {
        public:
            Reverse( T IterTemp ) : Reverse<T>::iterator_adaptor_( IterTemp ) {};
            void increment( void )
            { --this->base_reference(); }
    };
    Je n'ai défini qu'increment(void), et non increment(int), decrement, etc. pour simplifier l'example, mais les définir donne le même résultat.
    Quand je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main(void)
    {
        int oh[] = { 3, 5, 7 };
        Reverse <int*> ItoBegin( oh + 2 ), ItoEnd( oh - 1 );
        std::copy( ItoBegin, ItoEnd, std::ostream_iterator<int>( std::cout, "\n" ) );
        return 0;    
    }
    Et que j'exécute :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ g++ -Wall -o test test.cpp
    $ ./test
    Je n'ai pas d'erreur de compilation ni runtime, mais je n'obtient pas d'output. Tandis qu'avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void fonc( int a )
    { std::cout    << a << "\n"; }
    int main(void)
    {
        int oh[] = { 3, 5, 7 };
        Reverse <int*> ItoBegin( oh + 2 ), ItoEnd( oh - 1 );
        std::for_each( ItoBegin, ItoEnd, fonc );
        return 0;    
    }
    J'obtiens :
    Comment cela se fait-il ?

    Mon deuxième problème :
    J'instancie mon Reverse via :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
            Reverse( T IterTemp ) : Reverse<T>::iterator_adaptor_( IterTemp ) {};
    parce que j'ai vu que cela semblait marcher. Cependant, je me demande pourquoi cette ligne est nécessaire. En effet, dans la définition d'iterator_adaptor dans <boost/iterator/iterator_adaptor.hpp>, on trouve :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
      template <
          class Derived
        , class Base
        ...  >
      class iterator_adaptor
       ...  {
          ...
       public:
          ...
          explicit iterator_adaptor(Base const &iter)
              : m_iterator(iter)
          {
          }
          ...
       private:
          Base m_iterator;
      };
    Or, quand j'essaie de retirer le constructor Reverse( T IterTemp ), pensant que le constructor ci-dessus suffira, j'obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ...: In function ‘int main()’:
    ...:21:34: error: no matching function for call to ‘Reverse<int*>::Reverse(int*)’
    ...:7:1: note: candidates are: Reverse<int*>::Reverse()
    ...:7:1: note:                 Reverse<int*>::Reverse(const Reverse<int*>&)
    Comme si le compilateur ignorait l'existence du constructor iterator_adaptor(Base const&iter), ou considérait que Base a pour type Reverse<int*>& et non int*.
    Comment cela se fait-il ?

    Merci beaucoup !

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Août 2007
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 39
    Par défaut
    Problème 1 résolu :
    Reverse<T> est considéré comme un itérateur random access, puisque T (int*) est random access. En conséquence, copy() calcule la distance entre ItoBegin et ItoEnd avec "ItoEnd - ItoBegin" (il s'agit d'une optimisation : avec un iterator non-random access, copy effectue ce calcul via une succession de ++). Il faut donc définir distance_to(), en plus d'incrément() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    		typename boost::iterator_traits<Reverse<T> >::difference_type distance_to( const Reverse<T>& Other ) const
    		{ return this->base_reference() - Other.base_reference(); }
    En gros, ma classe Reverse<T> faisaient de fausses assomptions sur le template (-> que T soit au maximum bidirectionnel, et pas random access).

    Problème 2 (encore non résolu) :
    J'ai réussi à le réduire à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include  <boost/iterator_adaptors.hpp>
     
    template <class T>
    struct Reverse : public boost::iterator_adaptor <Reverse<T>, T> 
    {
        Reverse( T IterTemp ) : Reverse<T>::iterator_adaptor_( IterTemp ) {};
    };
     
    int main(void)
    {
    	int oh[] = { 10, 20, 30 };
    	Reverse<int*> Iter( oh );
      return 0;    
    }
    Le problème est que je ne comprends pas pourquoi je dois rajouter "Reverse( T IterTemp ) : ... {};", dans la mesure où l'header définit déjà un constructor prenant un argument T (cf plus haut). J'ai l'impression que cela a à voir avec le fait que le premier élément du template de Reverse est son propre type ("Curiously Recurring Template Pattern (CRTP)"), ce qui perturbe le compilateur, mais j'aimerais réussir à mieux comprendre cette idée.
    Merci

Discussions similaires

  1. installation de boost
    Par heinquoi dans le forum Bibliothèques
    Réponses: 2
    Dernier message: 18/04/2005, 17h20
  2. Installation de boost (librairie)
    Par dj.motte dans le forum Autres éditeurs
    Réponses: 14
    Dernier message: 21/11/2004, 03h11
  3. boost::serialize
    Par Fry dans le forum Bibliothèques
    Réponses: 6
    Dernier message: 05/11/2004, 18h03
  4. [Plugin] Comment instantier certaines classes de ANT ?
    Par relivio dans le forum Eclipse Platform
    Réponses: 2
    Dernier message: 01/04/2004, 15h45
  5. cherchecomment utiliser boost sous linux
    Par Krost dans le forum Autres éditeurs
    Réponses: 1
    Dernier message: 25/02/2004, 22h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo