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 :

"using typename" vs gcc version


Sujet :

C++

  1. #1
    Membre confirmé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Points : 455
    Points
    455
    Billets dans le blog
    1
    Par défaut "using typename" vs gcc version
    Bonjour,

    je me suis fait une petite classe Map qui hérite de std::map et j'ai un souci de compilation selon la version de gcc :

    Voici le début de ma 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
     
    template <typename Key,typename Value> class Map : public std::map<Key,Value>
        {
        public:
            using typename std::map<Key,Value>::const_iterator ;
            using std::map<Key,Value>::operator [] ;
            using std::map<Key,Value>::insert ;
            using std::map<Key,Value>::begin ;
            using std::map<Key,Value>::find ;
            using std::map<Key,Value>::end ;
     
            Map & add ( const Map & other )
                {
                for ( const_iterator i = other.begin() ; i != other.end() ; ++i )  // <--- ligne de l'erreur
                    (*this)[i->first] = i->second ;
                return *this ;
                }
    avec la version de gcc 5.3.1, ça compile sans problème et sans warning.
    Avec la version 4.4.7, j'ai cette erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    In member function "common::Map<Key, Value>& common::Map<Key, Value>::add(const common::Map<Key, Value>&)":
    error: expected ";" before "i"
    error: "i" was not declared in this scope
    Et là, mes maigres connaissances de c++ trouvent leur limite...
    Y a-t-il moyen de trouver une syntaxe équivalente qui compile avec les 2 versions de gcc ?

    Merci d'avance !
    Captain'Flam
    anciennement Sopsag, aka Hadrien
    Win seven x64 & Win 10 / Visual 2017 / Python 2.7 / Eclipse

  2. #2
    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
    c'est parce que sans l'option --std=c++0x, gcc 4.4 compile en C++03, et qu'alors, using ne pouvait pas servir pour introduire un nom de type.
    essaye d'écrire for ( typename const_iterator i = other.begin() ; i != other.end() ; ++i )D'une manière générale, il ne faut pas hériter des conteneurs de la STL (qui ne fournissent pas de destructeur virtuel)

    Si vraiment tu veux ajouter des fonctionnalités supplémentaires, tu peux définir des fonctions libres, et même certains opérateurs.
    Par exemple, il m'arrive d'ajouter un opérateur / aux maps:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    namespace operators {
    template <typename K, typename V, typename C, typename A>
    V* operator / (std::map<K, V, C, A> & map, K const& key) {
        typename std::map<K, V, C, A>::iterator it = m.find(key);
        return it != map.end() ? &*it : std::nullptr;
    }
    }
    Autant que possible, évite l'antique gcc 4.4, essaie de convaincre de passer à une version récente: la série 6.x est en cours, la 5.2 est très bien, et tu peux regarder 4.7, 4.8 ou 4.9
    Cela améliorerait les performances du code produit, certes, mais surtout la précision des messages du compilateur (ainsi que de supporter le C++ moderne d'il y a 5 ans)
    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

  3. #3
    Membre confirmé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Points : 455
    Points
    455
    Billets dans le blog
    1
    Par défaut
    Merci beaucoup de ta réponse précise et instructive.

    Le problème a été résolu en passant à gcc 5.

    --> nous utilisons cmake sur une machine sur laquelle coexistent gcc 4 et gcc 5.
    et pour une raison que j'ignore, cmake .. -G "Unix Makefiles" produit un makefile qui utilise gcc 4, alors que which gcc me renvoie le chemin de gcc 5...
    Du coup, j'ai ajouté -DCMAKE_CXX_COMPILER="`which g++`" à ma ligne de commande, et ça marche impec' !

    Et en réponse à ton conseil, je dirais que quand je créé des classes qui héritent de celles de la stl, c'est uniquement pour y ajouter des méthodes/opérateurs.
    Donc je n'ai pas problème avec l'absence de destructeur virtuel.
    Captain'Flam
    anciennement Sopsag, aka Hadrien
    Win seven x64 & Win 10 / Visual 2017 / Python 2.7 / Eclipse

  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
    Et tu n'as jamais un pointeur de std::map dans lequel tu mettrais une de tes Map?
    Jamais du tout?

    Il vaut toujours mieux des fonctions externes quand c'est possible.
    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
    Membre confirmé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Points : 455
    Points
    455
    Billets dans le blog
    1
    Par défaut
    Et tu n'as jamais un pointeur de std::map dans lequel tu mettrais une de tes Map?
    Quand bien même... cela pose-t-il un problème ?
    Si j'ai un pointeur de std::map pointant sur une de mes Map, je ne pourrais pas appeler les méthodes ajoutées par les Map, mais c'est tout...
    Me trompé-je ?
    Captain'Flam
    anciennement Sopsag, aka Hadrien
    Win seven x64 & Win 10 / Visual 2017 / Python 2.7 / Eclipse

  6. #6
    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
    Oui, parce que si tu fais un delete sur ce pointeur, ta Map n'est pas correctement effacée, pour cause de "undefined behaviour".

    Les classes de la STL sont conçues pour ne pas être héritées
    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

  7. #7
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    ... publiquement (si l'utilisateur fait, directement ou indirectement, une allocation dynamique de Map, et un delete sur un pointeur de std::map, ça posera problème (sauf si Map ne rajoute pas de données membre ?)).
    (J'ai toujours rapproché cette usage de la non conforming inheritance (Eiffel), sans jamais trop regarder.)

    En héritage private, ça ne pose pas de souci.
    (mais il faut faire les using qui vont bien si on veut ramener des choses de std::map publiquement.)

  8. #8
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Citation Envoyé par Ehonn Voir le message
    [...] sauf si Map ne rajoute pas de données membre ?
    Le problème n'arrive qu'avec les membres qui ont un destructeur puisque qu'ils ne sera pas appelé.

  9. #9
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Tu veux dire qu'on peut rajouter des données membres comme les types de bases ? std::array ? sans aucun souci ?

  10. #10
    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 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Le seul truc c'est que le destructeur de la classe dérivée ne sera pas appelée si le typage statique est la classe mère.
    Donc le code de ton destructeur ne sera pas appelé.
    Ca ne change rien au fait qu'une fois une variable détruite son destructeur est toujours appelé.
    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.

  11. #11
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Comme l'indique Bousk, c'est le typage statique qui compte en l'absence de destructeur virtuel.
    Donc tant qu'aucun membres ou sous membre n'a de destructeur, tout ira bien (std::array<int,n> -> ok, std::array<std::string,n> -> non).

    C'est la subtile différence entre une fonction vide et une fonction qui n'est pas utilisée :p.

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

Discussions similaires

  1. Quote et double quote
    Par aktos dans le forum Langage
    Réponses: 8
    Dernier message: 05/01/2007, 19h55

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