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 :

surcharger std::vector pour en faire un vecteur circulaire


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 64
    Points : 40
    Points
    40
    Par défaut surcharger std::vector pour en faire un vecteur circulaire
    Bonjour,

    J'ai surchargé std::vector afin de créer un vecteur circulaire. L'idée c'est que si mon vecteur fait une taille de 10, Vect.at(12) me renvoie le troisème objet, ou alors Vect.at(-2) me renvoie l'avant dernier objet ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    class CircularVector : public std::vector<T_Obj>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template<typename T_Obj>
    T_Obj &CircularVector<T_Obj>::at(const qint32 &adr) {
     
        qint32 p;
        adr >= 0 ? p = adr%size_ : p = size_ - (-adr)%size_;
     
        return vector<T_Obj>::at(p);
    }
    Cette classe m'est super utile

    Par contre je ne sais pas du tout comment surcharger iterator

    Pour pouvoir faire quelque chose du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for(std::vector<float>::iterator it = Vector.begin(); it < Vector.end() + 8; ++it) {...}
    Merci d'avance

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    - de l'héritage public pour ça est très malvenu
    - quel serait le sens d'itérer jusqu'à "la fin + 8" ? Tu veux passer en revue plusieurs fois les premiers éléments ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    qint32 p;
        adr >= 0 ? p = adr%size_ : p = size_ - (-adr)%size_;
    Cette écriture est bizarre parce que normalement un ternaire ce serait qint32 p = adr >= 0 ? adr%size_ : size_ - (-adr)%size_;
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 469
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 469
    Points : 6 102
    Points
    6 102
    Par défaut
    Bonjour,

    Coder une classe CircularVector :
    • est long si on fait proprement de l'encapsulation,
    • oblige à transformer les std::vector existants en CircularVector pour pouvoir profiter de la fonctionnalité et
    • n'étend que std::vector, pas les autres types de conteneurs.


    Voici une autre solution qui n'a pas les inconvénients ci-dessus. Elle marche à la fois avec std::vector, std::array et std::deque :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    template<class ContainerT, class IndexT>
    typename ContainerT::reference getElementByCircularIndex(ContainerT& container, IndexT index) {
    	const auto size      = container.size();
    	const auto realIndex = index >= 0 ? index%size : size - (-index)%size;
    	return container[realIndex];
    }
     
    template<class ContainerT, class IndexT>
    typename ContainerT::const_reference getElementByCircularIndex(const ContainerT& container, IndexT index) {
    	const auto size      = container.size();
    	const auto realIndex = index >= 0 ? index%size : size - (-index)%size;
    	return container[realIndex];
    }
    Voici encore une autre solution, qui supporte encore plus de types de conteneurs, avec un exemple de code qui l'utilise :
    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
    #include <array>
    #include <deque>
    #include <iostream>
    #include <iterator>
    #include <list>
    #include <string>
    #include <vector>
     
    auto getElementByCircularIndex = [](auto& container, auto index) {
    	const auto size          = container.size();
    	auto       inputIterator = container.begin();
    	const auto offset        = index >= 0 ? index%size : size - (-index)%size;
    	std::advance(inputIterator, offset);
    	return *inputIterator;
    };
     
    int main()
    {
    	const std::array <std::string, 7> daysArray  = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
    	const std::deque <std::string>    daysDeque  = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
    	const std::list  <std::string>    daysList   = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
    	const std::vector<std::string>    daysVector = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
    	std::cout << getElementByCircularIndex(daysArray,  14)  << " "; // prints "Monday"
    	std::cout << getElementByCircularIndex(daysDeque,  2)   << " "; // prints "Wednesday"
    	std::cout << getElementByCircularIndex(daysList,   74)  << " "; // prints "Friday"
    	std::cout << getElementByCircularIndex(daysVector, -15) << " "; // prints "Sunday"
    	return 0;
    }

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    De plus, il existe déjà, dans Boost, un circular buffer efficace, testé, validé, amélioré.
    http://www.boost.org/doc/libs/releas...ar_buffer.html

    Je te déconseille vivement d'hériter de vector, pour plusieurs raisons, dont l'absence de destructeur virtuel.
    Si tu tiens à le coder toi-même, préfère la composition (contenir un vector comme membre).
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  5. #5
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Une solution pour sortir de ton problème, c'est de comprendre que tu as plusieurs visions possibles de ton conteneur:
    • Itération sur l'ensemble des valeurs, de la première à la dernière (le segment [0 .. n-1])
    • Depuis une position donnée, l'ensemble des valeurs (le segment [i .. n-1] puis le segment [0 .. i-1]
    • En boucle infinie.

    La solution la plus simple serait d'avoir un mécanisme de vues itérables. Ces vues contenant a peine plus qu'une référence sur le conteneur, elles sont "gratuites".
    La vue "un cycle" comprenant un point de départ.
    La vue "infinie" dont l'itérateur end est inatteignable depuis un itérateur vers une valeur valide. (par exemple, en interne, un optional<size_type>)

    De là, il suffit de fournir des fonctions utilitaires dans ta classe, qui retournerait une vue.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    cylic_store<int> store {1,2,3,4};
    for(auto i : store.from(3)) cout << i << endl;
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

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

Discussions similaires

  1. Réponses: 10
    Dernier message: 11/09/2017, 04h10
  2. besoin d'aide pour "configurer" un std::vector
    Par mazertys17 dans le forum C++
    Réponses: 12
    Dernier message: 27/04/2015, 13h47
  3. Surcharge opérateur std::vector
    Par boutor dans le forum C++
    Réponses: 24
    Dernier message: 31/08/2011, 15h00
  4. Créer un vecteur de texte pour y faire appel
    Par Aphelio dans le forum MATLAB
    Réponses: 4
    Dernier message: 07/05/2011, 21h11
  5. std::vector, taille du vecteur-> quel fonction
    Par toutounesan dans le forum C++
    Réponses: 3
    Dernier message: 11/09/2007, 15h43

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