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

Langage C++ Discussion :

template et namespace


Sujet :

Langage C++

  1. #1
    Futur Membre du Club
    Inscrit en
    Octobre 2003
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 4
    Par défaut template et namespace
    Bonjour à tous

    J'ai quelques soucis sur la déclaration d'un template dans un namespace (__gnu_cxx). Faut dire que je suis un peu débutant en C++...

    Le code provient d'un programme sous Linux, et je dois le porter sur Windows.
    Sous linux, normalement on importe <ext\hash_map> et <ext\hash_set>, et dans mon cas j'ai remplacé par <hash_map> <hash_set>.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <hash_map>
    #include <hash_set>	
    #include "IPvXAddress.h"
     
    #define ...
     
    namespace __gnu_cxx
    {
     
        template<> struct hash< IPvXAddress >
        {
    ...
    Là j'ai un problème à la ligne où est declaré la structure hash :
    - syntax error : missing ';' before '<'
    - explicit specialization; '__gnu_cxx::hash' is not a specialization of a class template

    Là je ne sais pas tellement quoi faire. En relisant le document C++ de H. Garreta je ne retrouve pas ce genre de syntaxe pour les templates.

    2nd header :
    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
    ...
    #include "IPvXAddress.h"
    #include "HashFunc.h"
     
    using namespace __gnu_cxx;
    using namespace std;
     
    class TransportAddress
    {
    public:
            class hashFcn
        {
        public:
            size_t operator()( const TransportAddress& h1 ) const
            {
                return h1.hash();
            }
        };
     
    public:
        // a hashed set of TransportAddresses
        typedef hash_set <TransportAddress, hashFcn> Set; 
    public:
        IPvXAddress ip;
    ...
    Et ici également un problème de syntaxe à la ligne où je définie hash_set (syntax error : missing ';' before '<'). C'est assez similaire au problème plus haut je suppose.

    Voilà, j'espere avoir été assez clair.

    Merci d'avance

    bon week end

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Salut,

    Le principe de base à savoir, c'est que tous les identifiants préfixés par un ou deux underscore (comme c'est le cas pour __gnu_cxx) sont des identifiants "réservé" à l'implémentation du compilateur, et que tu dois éviter d'y avoir recours.

    Je crois même que c'est une obligation de la norme,même si, vu l'heure, je n'ai pas trop envie de vérifier

    Ainsi, l'espace de nom __gnu_cxx est principalement destiné à contenir (cf debug.h, c++config.h et autres hash_*.h)... l'espace de noms propre au débuggage de la stl (sous gcc, du moins) "__debug".

    Tout cela pour dire qu'il vaut mieux ajouter les fichiers "standards" fournis par le technical report (TR1) en incluant les fichier hash_(map|set|table) qui se trouvent dans le dossier tr1 (et qui, pour le coup, sont accessible dans l'espace de noms tr1 qui est lui même dans l'espace de nom std).

    Ceci étant dit, il est impossible de fournir une spécialisation partielle pour une classe template:

    Seules les méthodes de classes template peuvent être spécialisées partiellement pour créer un trait de politique.

    Si tu veux spécialiser toute la classe, il te faudra passer par une définition d'alias (typedef), selon un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef std::tr1::hash< IPvXAddress > IPVXhash;
    Si, de fait, il est possible de découvrir dans le fichier <string> (ou du moins dans un des fichiers inclus dans string) une déclaration du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template<class charT>struct char_traits;
    template <> struct char_traits<char>;
    template <> struct char_traits<wchar_t>;
    c'est en fait qu'il s'agit de déclarations anticipées pour :
    1. une structure char_traits tout à fait template
    2. la structure char_traits utilisant spécifiquement des caractères
    3. la structure char_traits utilisant spécifiquement des caractères unicode
    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

  3. #3
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Le principe de base à savoir, c'est que tous les identifiants préfixés par un ou deux underscore (comme c'est le cas pour __gnu_cxx) sont des identifiants "réservé" à l'implémentation du compilateur, et que tu dois éviter d'y avoir recours.
    Tu ne dois pas définir de tels identificateurs.

    Si tu veux utiliser une extension qui utilise un identificateur réservé, tu dois utiliser cet identificateur réservé, par définition.

    Citation Envoyé par koala01 Voir le message
    Je crois même que c'est une obligation de la norme,même si, vu l'heure, je n'ai pas trop envie de vérifier
    Par définition, s'il utilise une extension de gcc, il ne peut pas se référer à la norme.

    Citation Envoyé par koala01 Voir le message
    Ainsi, l'espace de nom __gnu_cxx est principalement destiné à contenir (cf debug.h, c++config.h et autres hash_*.h)... l'espace de noms propre au débuggage de la stl (sous gcc, du moins) "__debug".
    __gnu_cxx est destiné, il me semble, à contenir les extensions gcc.

    Citation Envoyé par koala01 Voir le message
    Tout cela pour dire qu'il vaut mieux ajouter les fichiers "standards" fournis par le technical report (TR1) en incluant les fichier hash_(map|set|table) qui se trouvent dans le dossier tr1 (et qui, pour le coup, sont accessible dans l'espace de noms tr1 qui est lui même dans l'espace de nom std).
    Sauf s'il existe des différences entre les conteneurs tr1 et les ceux implémentés comme extensions par gcc (je suis quasiment sûr que c'est le cas), et qu'il dépend de ces différences.

    Citation Envoyé par koala01 Voir le message
    Ceci étant dit, il est impossible de fournir une spécialisation partielle pour une classe template:
    Bien sûr que si! Une spécialisation partielle ne peut être déclarée que pour une classe générique.

    Citation Envoyé par koala01 Voir le message
    Seules les méthodes de classes template peuvent être spécialisées partiellement pour créer un trait de politique.
    Un membre de classe générique (non membre générique) ne peut pas être spécialisé (ni partiellement, ni explicitement), si on ne spécialise pas la classe elle-même.

    Et si on spécialise la classe, le membre n'a plus à être spécialisé.

    Donc un membre de classe générique ne peut pas être spécialisé.

    Citation Envoyé par koala01 Voir le message
    Si tu veux spécialiser toute la classe, il te faudra passer par une définition d'alias (typedef), selon un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef std::tr1::hash< IPvXAddress > IPVXhash;
    Il n'y a aucun besoin de typedef pour définir une spécialisation.

    Citation Envoyé par koala01 Voir le message
    Si, de fait, il est possible de découvrir dans le fichier <string> (ou du moins dans un des fichiers inclus dans string) une déclaration du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template<class charT>struct char_traits;
    template <> struct char_traits<char>;
    template <> struct char_traits<wchar_t>;
    c'est en fait qu'il s'agit de déclarations anticipées pour :
    1. une structure char_traits tout à fait template
    2. la structure char_traits utilisant spécifiquement des caractères
    3. la structure char_traits utilisant spécifiquement des caractères unicode
    Ce sont des déclarations de spécialisation explicite de la forme générique char_traits. (Et on voit qu'il n'est pas besoin de typedef.)

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par ben56 Voir le message
    J'ai quelques soucis sur la déclaration d'un template dans un namespace (__gnu_cxx). Faut dire que je suis un peu débutant en C++...
    Pour un débutant, la spécialisation de formes génériques c'est déjà pas mal.

    Citation Envoyé par ben56 Voir le message
    Le code provient d'un programme sous Linux, et je dois le porter sur Windows.
    Sous linux, normalement on importe <ext\hash_map> et <ext\hash_set>, et dans mon cas j'ai remplacé par <hash_map> <hash_set>.
    Des \ sous linux?

    Avec gcc tu veux dire.

    Citation Envoyé par ben56 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <hash_map>
    #include <hash_set>	
    #include "IPvXAddress.h"
     
    #define ...
     
    namespace __gnu_cxx
    {
     
        template<> struct hash< IPvXAddress >
        {
    ...
    Là j'ai un problème à la ligne où est declaré la structure hash :
    - syntax error : missing ';' before '<'
    - explicit specialization; '__gnu_cxx::hash' is not a specialization of a class template
    Il n'y a pas de forme générique de classe (= class template) nommée __gnu_cxx::hash déclarée.

    Citation Envoyé par ben56 Voir le message
    2nd header :
    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
    ...
    #include "IPvXAddress.h"
    #include "HashFunc.h"
     
    using namespace __gnu_cxx;
    using namespace std;
     
    class TransportAddress
    {
    public:
            class hashFcn
        {
        public:
            size_t operator()( const TransportAddress& h1 ) const
            {
                return h1.hash();
            }
        };
     
    public:
        // a hashed set of TransportAddresses
        typedef hash_set <TransportAddress, hashFcn> Set; 
    public:
        IPvXAddress ip;
    ...
    Et ici également un problème de syntaxe à la ligne où je définie hash_set (syntax error : missing ';' before '<'). C'est assez similaire au problème plus haut je suppose.
    C'est clair : il n'y a pas de forme générique de classe hash_set déclarée dans les espaces référentiels recherchés (global, std et __gnu_cxx).

  5. #5
    Futur Membre du Club
    Inscrit en
    Octobre 2003
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 4
    Par défaut
    Merci déjà pour vos réponses

    Si je comprends bien, pour le 2nd cas, il suffit de faire
    #include <hash_set>

    En référence à :
    http://msdn2.microsoft.com/en-us/library/00htc7h2(VS.80).aspx


    Dites moi si je me trompe...

    Sinon, pour le 1er cas (fichier hashfunc.h), je suis un peu perdu

    Ces lignes de codes proviennent du code d'origine, que j'ai compilé sans difficulté avec g++ sous linux.
    Pour info, byteswap.h permet de définir la structure bswap_32 utilisée à la place des "..."

    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
    #ifndef __HASHFUNC
    #define __HASHFUNC
     
    #include <ext/hash_map>
    #include <byteswap.h>
     
    #include "IPvXAddress.h"
     
    namespace __gnu_cxx
    {
        /**
         * defines a hash function for IPvXAddress
         */
        template<> struct hash< IPvXAddress >
        {
    	/**
         * hash function for IPvXaddress
         * 
         * @param addr the IPvXAddress to hash
         * @return the hashed IPvXAddress
         */
        size_t operator()(const IPvXAddress& addr) const
    	{
    	    ...
    	}
        };
    }
    #endif
    Quand tu me dis
    Il n'y a pas de forme générique de classe (= class template) nommée __gnu_cxx::hash déclarée.
    Comment g++ arrive à inclure ce fichier dans la compilation alors ???

    Il faut que je passe par une définition d'alias comme le dis kaola01 ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef std::tr1::hash< IPvXAddress > IPVXhash;
    (je peux pas essayer avant lundi ou mardi)


    Bonne soirée et bon dimanche

  6. #6
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par ben56 Voir le message
    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
    #ifndef __HASHFUNC
    #define __HASHFUNC
     
    #include <ext/hash_map>
    ...
    #include "IPvXAddress.h"
     
    namespace __gnu_cxx
    {
        /**
         * defines a hash function for IPvXAddress
         */
        template<> struct hash< IPvXAddress >
        {
    ...
        };
    }
    #endif
    Comment g++ arrive à inclure ce fichier dans la compilation alors ???
    Est-ce que ce fichier est compilable tout seul? (Sans aucun autre include avant.)

    Citation Envoyé par ben56 Voir le message
    Il faut que je passe par une définition d'alias comme le dis kaola01 ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef std::tr1::hash< IPvXAddress > IPVXhash;
    Ça n'a absolument rien à voir.

  7. #7
    Futur Membre du Club
    Inscrit en
    Octobre 2003
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 4
    Par défaut
    Pour le moment tout ce que je peux dire c'est qu'avec ça dans le fichier (aucun autre include, aucune autre ligne de commande), je n'avais pas eu de difficulté lors de la compilation avec g++

    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
    #ifndef __HASHFUNC
    #define __HASHFUNC
     
    #include <ext/hash_map>
    #include <byteswap.h>
     
    #include <IPvXAddress.h>
     
    namespace __gnu_cxx
    {
        /**
         * defines a hash function for IPvXAddress
         */
        template<> struct hash< IPvXAddress >
        {
    	/**
         * hash function for IPvXaddress
         * 
         * @param addr the IPvXAddress to hash
         * @return the hashed IPvXAddress
         */
        size_t operator()(const IPvXAddress& addr) const
    	{
    	    if( addr.isIPv6() ) {
    		return bswap_32(addr.get6().words()[0]) ^ bswap_32(addr.get6().words()[1]) ^ 
    		    bswap_32(addr.get6().words()[2]) ^ bswap_32(addr.get6().words()[3]);
    	    } else {
    		return bswap_32(addr.get4().getInt());
    	    }
    	}
        };
    }
     
    #endif

  8. #8
    Futur Membre du Club
    Inscrit en
    Octobre 2003
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 4
    Par défaut
    Bonjour,

    J'ai pu réseoudre le 1er problème avec la structure hash, j'ai utilisé la syntaxe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template<class IPvXAddress> struct hash
    Par contre, pour le 2nd problème, l'ajout de hash_set ne fait rien. Le plus etonnant c'est que hash_set contient à une ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef hash_set<_Kty, _Tr, _Alloc> _Myt;
    C'est exactement la syntaxe que j'utilise, alors je ne comprends pas...

    Merci d'avance pour votre aide

Discussions similaires

  1. Réponses: 4
    Dernier message: 23/03/2011, 12h07
  2. [XSLT][namespace] Création worksheet via template
    Par Graineur dans le forum XSL/XSLT/XPATH
    Réponses: 8
    Dernier message: 09/11/2010, 00h23
  3. Template et namespace
    Par bolhrak dans le forum Langage
    Réponses: 2
    Dernier message: 11/08/2007, 01h51
  4. Template, namespace ?
    Par olivier1978 dans le forum Langage
    Réponses: 5
    Dernier message: 11/02/2007, 19h05
  5. xsl:Template sur un élément sans namespace
    Par dust45 dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 27/10/2005, 16h52

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