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

C++ Discussion :

Iterateurs et discrete_distribution


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Juin 2008
    Messages
    522
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 522
    Par défaut Iterateurs et discrete_distribution
    Bonjour,

    J'ai une liste d'éléments (int) et de poids (double) en entrée, je veux faire un tirage aléatoire d'un élément pondéré par les poids donnés.
    L'entrée est sous forme d'un vector<int, double>.
    La classe discrete_distribution semble idéale pour le tirage, cependant le format de l'entrée n'est pas adapté au constructeur.
    Première solution: je copie tout les poids dans un vector<double> et j'ai ma distribution. Sauf que ce n'est pas élégant, et ça demande de dupliquer les poids et donc de perdre du temps.
    Je me suis donc tourné vers une deuxième solution: surcharger un iterator: j'ai donc la classe
    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
    18
    template <typename U, typename V>
    class secondTermIterator : public std::vector<V>::iterator{//std::iterator<std::bidirectional_iterator_tag,std::pair<U,V> > {
    public:
     typedef std::pair<U,V> pair;
     typedef typename std::vector<pair >::iterator iterator;
     secondTermIterator() {}
     secondTermIterator(iterator j) : i(j) {}
     secondTermIterator& operator++() { ++i; return *this; }
     secondTermIterator operator++(int) { auto tmp = *this; ++(*this); return tmp; }
     secondTermIterator& operator--() { --i; return *this; }
     secondTermIterator operator--(int) { auto tmp = *this; --(*this); return tmp; }
     bool operator==(secondTermIterator j) const { return i == j.i; }
     bool operator!=(secondTermIterator j) const { return !(*this == j); }
     V& operator*() { return i->second; }
     V* operator->() { return &i->second; }
    protected:
     iterator i;
    };
    Bon, tout a l'air bien de ce côté, maintenant on crée la distribution:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     vector<pair<int, double> > c;
    //On remplie c ici, par exemple:
        c.push_back(pair<int, double>(42,4.2));
        c.push_back(pair<int, double>(53,1.7));
        c.push_back(pair<int, double>(102,3.3));
    //
     
    auto itb=secondTermIterator<size_t, double>(c.begin());
    auto ite=secondTermIterator<size_t, double>(c.end());
    discrete_distribution<int> distribution(itb,ite);
     
    //On vérifie que la construction est correcte
    for (double x:distribution.probabilities()) std::cout << x << " ";
    Et là, distribution.probabilities est le singleton {1}. Alors ma question est: pourquoi l'itérateur est il ignoré ?

    Merci de vos éclaircissements.

  2. #2
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Bonjour,

    L'erreur à l'exécution vient du fait que ton secondTermIterator dérive publiquement de std::vector<V>::iterator, donc est implicitement convertible en std::vector<V>::iterator. Or, tu n'initialises pas la valeur de ta classe parente dans tes constructeurs.
    Le constructeur de std::discrete_distribution<int> se retrouve avec deux arguments qu'il a décidé de convertir en std::vector<double>::iterator avec des valeurs indéterminées. Dans ton cas, elles avaient probablement la même valeur, donc ta distribution n'a eu que le poids 1.

    Pour être valide, ton itérateur a besoin de respecter le concept InputIterator.

    En partant de ton code, voici quelques modifs mineures pour qu'il marche :
    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    #include <iostream>
    #include <random>
    #include <vector>
     
    template <typename U, typename V>
    class secondTermIterator {
    public:
    	typedef std::pair<U,V>                              pair;
    	typedef typename std::vector<pair>::iterator        iterator;
    	typedef V                                           value_type;
    	typedef std::input_iterator_tag                     iterator_category;
    	typedef typename std::vector<pair>::difference_type difference_type;
    	typedef value_type&                                 reference;
    	typedef value_type*                                 pointer;
    	explicit secondTermIterator(iterator j) : i(j) {}
    	secondTermIterator& operator++() { ++i; return *this; }
    	secondTermIterator operator++(int) { auto tmp = *this; ++(*this); return tmp; }
    	bool operator==(secondTermIterator j) const { return i == j.i; }
    	bool operator!=(secondTermIterator j) const { return !(*this == j); }
    	reference operator*()  const { return  i->second; }
    	pointer   operator->() const { return &i->second; }
    protected:
    	iterator i;
    };
     
    int main()
    {
    	std::vector<std::pair<int, double> > c;
    	c.push_back(std::pair<int, double>(42,4.2));
    	c.push_back(std::pair<int, double>(53,1.7));
    	c.push_back(std::pair<int, double>(102,3.3));
     
    	auto itb=secondTermIterator<int, double>(c.begin());
    	auto ite=secondTermIterator<int, double>(c.end());
    	std::discrete_distribution<int> distribution(itb,ite);
     
    	// On vérifie que la construction est correcte.
    	for (double x : distribution.probabilities())
    		std::cout << x << " ";
    	return 0;
    }
    Cela dit, dans des projets professionnels, il faudra appliquer la maxime Premature optimization is the root of all evil (Donald Knuth) et privilégier la simplicité du code. Par exemple, il ne faudra pas écrire tout ce code juste pour éviter de créer une variable intermédiaire std::vector<double>.

  3. #3
    Membre éclairé
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Juin 2008
    Messages
    522
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 522
    Par défaut
    Merci de ta réponse.
    En effet, la solution de passer par un vector<double> est facile et lisible. Tant que ça ne reste pas trop souvent utilisé, tout va bien.
    Mais, juste pour comprendre mon erreur et apprendre plus le C++, je devais demander.

    Cordialement

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Valeur par défaut pour un iterateur
    Par karmaki dans le forum C++
    Réponses: 10
    Dernier message: 20/05/2005, 08h22
  2. [Collections] hasPrevious() et previous() sur Iterateur de List
    Par red210 dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 19/04/2005, 14h00
  3. [Template] Pb d'iterateur generique
    Par Cyber@l dans le forum C++
    Réponses: 2
    Dernier message: 10/03/2005, 20h13
  4. ecrire un iterateur pour une classe
    Par Blowih dans le forum C++
    Réponses: 2
    Dernier message: 15/11/2004, 19h19
  5. STL iterateur pour queue
    Par Mathieu.Nanoux dans le forum SL & STL
    Réponses: 2
    Dernier message: 05/11/2004, 00h35

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