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 :

accéder aux valeurs d'une structure avec operateur []


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de BioKore
    Homme Profil pro
    Dresseur d'Alpaga
    Inscrit en
    Septembre 2016
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Dresseur d'Alpaga

    Informations forums :
    Inscription : Septembre 2016
    Messages : 300
    Par défaut accéder aux valeurs d'une structure avec operateur []
    Bonjour à tous,

    Dans le but de pratiquer un peu, je me propose de réaliser une bibliothèque permettant de réaliser des calculs vectoriels de base.
    Je suis donc parti sur des structures du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    struct vec3 {
    	float x,y,z;
    };
    et un fonctionnement similaire pour les tenseurs.

    Accéder aux valeurs de la structure via les opérateurs '.' est une bonne chose. Cependant, de manière à faciliter un peu les claculs ultérieurs, je souhaiterais pouvoir accéder aux différentes variables (x, y, z) via l'opérateur [] où, vec[0] retourne x, vec[1] retourne y etc... Idem pour les tenseurs: mat[0][0] retourne xx, mat[0][1] retourne xy etc..
    L'objectif est donc, comme présenté précédemment, de simplifier les algorithmes, mais aussi de laisser la possibilité à l'utilisateur d’appeler les valeurs soit via vec.x soit via vec[0].

    Je me suis dit que ce type de fonctionnement devais être trivial dans le sens où vec.x est sensé être à l'adresse &vec, vec.y est sensé être à l'adresse &vec+sizeof(float) etc... Mais visiblement, je dois ajuster mon approche car *(&vec+sizeof(float)) est de type vec3 et non float.

    Sans nécessairement me souffler la solution, une idée de la direction à prendre pour que je puisse répondre à ma problématique ?

    Merci d'avance.





    EDIT :

    Comme à mon habitude, poster mon message ici m'a apporté la réponse : "pourquoi diable coller un sizeof au milieu de tout ça ???"

    Réponse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    struct vec3 {
    	float x{.0f};
    	float y{.0f};
    	float z{.0f};
     
    	float & operator[](size_t const id) {
    		return *(&x+id);
    	}
    };
    ceci fonctionne.

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Citation Envoyé par BioKore Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct vec3 {
    	float x{.0f};
    	float y{.0f};
    	float z{.0f};
     
    	float & operator[](size_t const id) {
    		return *(&x+id);
    	}
    };
    ceci fonctionne.
    Ceci peut sembler fonctionner. Mais rien n'impose au compilateur de placer les x, y et z dans cet ordre.

    La capacité d'avoir un accès par index est intéressante, le seul moyen sûr serait de créer le tableau et d'y accéder par des alias:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct vec3 {
    	float tab[3] = {.0f,.0f,.0f};
    	float& x = tab[0];
    	float& y = tab[1];
    	float& z = tab[2];
    };
    Sauf que là le compilateur même s'il optimise en ne créant rien pour x,y et z (car ce sont des alias qui accèdent directement aux éléments du tableau), la structure devient de fait non copiable car contient des références. Et en plus le compilateur peut garder les 3 variables.
    Ce que je ferais serait d'utiliser x, y et z sous le forme de fonctions.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct vec3 {
    	float tab[3] = {.0f,.0f,.0f};
    	float& x() { return tab[0]; }
    	float& y() { return tab[1]; }
    	float& z() { return tab[2]; }
    };

  3. #3
    Membre éclairé Avatar de BioKore
    Homme Profil pro
    Dresseur d'Alpaga
    Inscrit en
    Septembre 2016
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Dresseur d'Alpaga

    Informations forums :
    Inscription : Septembre 2016
    Messages : 300
    Par défaut
    Je me disais bien qu'il devais tout de même y avoir un kwak quelque part

    Par contre, j'ai cru comprendre que les éléments d'une structure sont contigus. Suivant ce raisonnement, pourquoi le compilateur viendrait mettre du désordre la-dedans ?

    Sinon la méthode proposée me plait bien (avec les alias). Pour pallier au problème de la "copie" une surcharge du constructeur par copie devrait pouvoir tout remettre dans l'ordre non ?


    Merci encore.

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Citation Envoyé par BioKore Voir le message
    Par contre, j'ai cru comprendre que les éléments d'une structure sont contigus. Suivant ce raisonnement, pourquoi le compilateur viendrait mettre du désordre la-dedans ?
    Tu as raison, d'ailleurs aucun compilateur à ma connaissance ne s'amuse à changer l'ordre, d'autant que la construction doit se faire dans l'ordre de déclaration (et la destruction dans l'ordre inverse). Ta solution a donc un risque très minime. on pourrait ajouter un static_assert( &y == &x + 1 );static_assert( &z == &x + 2 ); pour se protéger de dérives. Cette méthode reste peut-être à préférer!

    Citation Envoyé par BioKore Voir le message
    Sinon la méthode proposée me plait bien (avec les alias). Pour pallier au problème de la "copie" une surcharge du constructeur par copie devrait pouvoir tout remettre dans l'ordre non ?
    Oui, il suffit certainement de les écrire. Mais je viens de faire un essai et l'optimiseur persiste à conserver 3 pointeurs dans la structure et en plus il s'en sert; ce qui crée une augmentation de taille et une indirection gênante.

    Malgré le risque de non portabilité, ta solution me semble donc meilleure.

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,
    Citation Envoyé par dalfab Voir le message
    la structure devient de fait non copiable car contient des références.
    Bah, ca, c'est encore assez facile à résoudre.

    Bien sur, il y a la possibilité de définir son propre constructeur (sans oublier son propre opérateur d'affectation), mais il y a peut-être même encore plus simple, car, le véritable problème vient du fait que, dans l'état actuel, tab n'est pas copiable

    Donc, si on s'arrange pour changer cet état de fait, par exemple, en utilisant une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct Vec3{
    public:
        float & operator[](size_t index){
            assert(index <3  && "index out of bound"); //essayer d'accéder à un indice trop élevé est une erreur de programmation
            return tab[index]; 
       }
    private:
        std::array<float, 3> tab;
    };
    Après, il est vrai que l'inclusion du fichier <array> sera invasive (comme l'inclusion de n'importe quel fichier d'en-tête dans un autre fichier d'en-tete), avec tout ce que cela comporte en termes d'augmentation du temps de compilation

    Mais, en termes de facilité, on ne trouvera rien de plus simple

    Comme souvent en C++, il faut être conscient que ce que l'on gagne d'un coté, on a de fortes chances de le perdre d'un autre. En l'occurrence, je m'abstiendrai donc bien de plaider pour une forme plutôt qu'une autre, d'autant plus qu'elles sont "assez facilement" interchangeables.

    Je me limite donc à proposer une alternative viable à un problème donné, en te laissant seul juge de celle que tu préfères
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Membre éclairé Avatar de BioKore
    Homme Profil pro
    Dresseur d'Alpaga
    Inscrit en
    Septembre 2016
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Dresseur d'Alpaga

    Informations forums :
    Inscription : Septembre 2016
    Messages : 300
    Par défaut
    De souvenir, glm permet le même emploi que j'attends ; j'ai bien essayé de voir ce à quoi ça ressemblait dans le code mais... Je pense avoir encore besoin de beaucoup de pratique avant de pouvoir comprendre l'implémentation des vecteurs de cette bibliothèque (d'autant plus que, pour glm, les formats doivent être compatibles avec gls non ?).

    Dans un premier temps, je vais continuer avec "ma" méthode. Je ferais évoluer là chose selon le besoin.


    Merci pour ces retours !

  7. #7
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Plutôt qu'une manipulation de pointeurs qui n'est pas garantie marcher, je préférerais passer par un switch qui lui, le serait:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    struct vec3 {
    	float x{.0f};
    	float y{.0f};
    	float z{.0f};
     
    	float & operator[](size_t const id) {
    		switch(id) {
    			case 0: return x;
    			case 1: return y;
    			case 2: return z;
    			default: throw std::domain_error("Seules les valeurs 0, 1 et 2 sont acceptées.");
    		}
    	}
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre éclairé Avatar de BioKore
    Homme Profil pro
    Dresseur d'Alpaga
    Inscrit en
    Septembre 2016
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Dresseur d'Alpaga

    Informations forums :
    Inscription : Septembre 2016
    Messages : 300
    Par défaut
    Oui !

    Effectivement, en passant un peu de temps dans les codes de GLM, je retrouve ce type de fonctionnement.
    Quel est l'avantage de passer par ce système ? n'est-ce pas plus "gourmand" en terme de ressources (tout est relatif) ?

    Sinon, je profite de ce petit retour pour poser cette question par rapport au code de GLM, comment s'utilisent les templates du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    namespace glm
    {
    	template<typename T, qualifier Q>
    	struct vec<4, T, Q>
    	{ 
    //...
    C'est la première fois que je vois une écriture comme struct<...>{};. Quelqu'un sait m'expliquer comment cela fonctionne ? Car je trouve ça plutôt pratique de pouvoir différencier les objets via le <...> plutôt que directement par le nom.
    J'ai essayé de créer une structure du même type pour des essais mais le compilateur me dit que ma structure n'est pas une class template...


    Merci !




    Ok, un simple template<size_t N, typename VT> struct vec; fait l'affaire Mais est-ce le meilleur moyen d'en arriver là ?
    A voir. En tout cas, j'arrive à faire fonctionner mes vecteurs.

    Merci encore !

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

Discussions similaires

  1. Accéder aux variables d'une structure
    Par Sansideevraiment dans le forum MATLAB
    Réponses: 1
    Dernier message: 06/10/2016, 16h43
  2. [Débutant] Accéder aux fields d'une structure
    Par MattM dans le forum MATLAB
    Réponses: 2
    Dernier message: 07/10/2015, 17h48
  3. [WB17] Accèder aux données d'une base SQL Server avec Webdev
    Par Biyoum dans le forum WebDev
    Réponses: 8
    Dernier message: 07/10/2014, 11h30
  4. Accéder aux valeurs des éléments d'une matrice
    Par alvinleetya dans le forum OpenCV
    Réponses: 5
    Dernier message: 01/10/2012, 16h19
  5. Réponses: 2
    Dernier message: 09/11/2007, 15h32

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