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 :

Traits pour classes définissant un typedef


Sujet :

Langage C++

  1. #1
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut Traits pour classes définissant un typedef
    Bonjour à tous,

    En attendant les concepts de C++0x, j'ai besoin d'écrire des classes de traits à utiliser avec boost::enable_if.

    J'ai un ensemble de classes ayant pour point commun de définir un typedef tail_sequence_node_t. J'aimerais écrire une classe de traits permettant de savoir si le type donné fait partie de cet ensemble de classes.
    Cette première tentative infructueuse me renvoie un message d'erreur à la compilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template<class T>
    struct is_sequence_node
    {
    	static const bool value = false;
    };
     
    template<class T>
    struct is_sequence_node<typename T::tail_sequence_node_t>
    {
    	static const bool value = true;
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    erreur: paramètres du patron ne sont pas utilisés dans la spécialisation partielle: 'T'
    Que faire ?
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  2. #2
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<class T>
    struct is_sequence_node
    {
    	static const bool value = (sizeof(typename T::tail_sequence_node_t) > 0 ) ? true : false;
    };
    Le problème ici c'est que ça compilera pas si y'a pas de type tail_sequence_node_t.

    Mais problème intéressant, je vais y réfléchir

  3. #3
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    J'ai pas creusé, mais il me semble qu'en utilisant SFINAE tu dois pouvoir t'en sortir.

  4. #4
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Si tu peux utiliser Boost.MPL :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    BOOST_MPL_HAS_XXX_TRAITS_DEF(tail_sequence_node_t)
    template <typename T>
    struct is_sequence_node
    {
      static const bool value = has_tail_sequence_node_t<T>::value;
    };
    devrait marcher

    EDIT : en gros, utiliser has_tail_sequence_node_t<T> directement

  5. #5
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Salut,
    J'ai pas creusé, mais il me semble qu'en utilisant SFINAE tu dois pouvoir t'en sortir.
    SFINAE marche pour la résolution de surcharges pour les appels de fonction. Là j'ai l'impression que Florian veut jouer sur la présence du type à la compilation et générer des valeurs pour les propager, alors qu'avec SFINAE on peut juste modifier un comportement à l'exécution si je ne m'abuse. Ou alors peut-être que je me trompe ?

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Alp Voir le message
    SFINAE marche pour la résolution de surcharges pour les appels de fonction. Là j'ai l'impression que Florian veut jouer sur la présence du type à la compilation et générer des valeurs pour les propager, alors qu'avec SFINAE on peut juste modifier un comportement à l'exécution si je ne m'abuse. Ou alors peut-être que je me trompe ?
    Il me semble que certains traits de boost sont définis comme ça.
    A l'arrache donc à affiner :
    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
    // repompage boost :
    typedef char yes_type;
    struct no_type
    {
       char padding[8];
    };
     
    template<class T>
       static yes_type check_sig(typename T::tail_sequence_node_t*);
    template<class T>
       static no_type check_sig(...);
     
    template<class T>
    struct is_sequence_node
    {
       static const bool value = sizeof(check_sig<T>(0))==sizeof(yes_type);
    };
     
    struct T1
    {
       typedef void tail_sequence_node_t;
    };
    struct T2
    {
    };
    int main()
    {
     
       std::cout<<std::boolalpha<<is_sequence_node<T1>::value<<std::endl;
       std::cout<<std::boolalpha<<is_sequence_node<T2>::value<<std::endl;
       return 0;
    }

  7. #7
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Il me semble que certains traits de boost sont définis comme ça.
    A l'arrache donc à affiner
    Ah oui, avec le retour covariant et le sizeof
    Bien vu.

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Alp Voir le message
    Ah oui, avec le retour covariant
    Euh, c'est pas un retour covariant ? Je croyais que le retour covariant c'était ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class A2{};
    class B2 : public A2{};
     
    class A1
    {
      virtual A2& f();
    };
    class B1 : public A1
    {
      virtual B2& f();
    };

  9. #9
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Dans le cadre de l'héritage c'est ça, mais de manière plus générale c'est quand une fonction du même nom peut retourner deux types différents. Là tout se joue sur le fait qu'il va choisir l'une ou l'autre des fonctions grâce à SFINAE, l'une retournant yes_type, d'une certaine taille, l'autre no_type, d'une autre taille, et que l'on peut comparer les tailles à la compilation, sans avoir à exécuter check.

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Alp Voir le message
    Dans le cadre de l'héritage c'est ça, mais de manière plus générale c'est quand une fonction du même nom peut retourner deux types différents. Là tout se joue sur le fait qu'il va choisir l'une ou l'autre des fonctions grâce à SFINAE, l'une retournant yes_type, d'une certaine taille, l'autre no_type, d'une autre taille, et que l'on peut comparer les tailles à la compilation, sans avoir à exécuter check.
    Ce qui me perturbait c'est que covariant veut littéralement dire 'varie avec'. Ici, il s'agit de deux types retour complètement distincts.

  11. #11
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    Merci pour toutes vos réponses

    Citation Envoyé par Alp Voir le message
    SFINAE marche pour la résolution de surcharges pour les appels de fonction. Là j'ai l'impression que Florian veut jouer sur la présence du type à la compilation et générer des valeurs pour les propager, alors qu'avec SFINAE on peut juste modifier un comportement à l'exécution si je ne m'abuse. Ou alors peut-être que je me trompe ?
    Il me semble plutôt que SFINAE marche à la compilation. En fait, elle va déterminer, pour un type donné, la présence ou l'absence d'une fonction parmi l'ensemble des fonctions candidates à la résolution de la surcharge. Cette résolution, elle, se fait bien à l'exécution.

    Sinon, ce que je veux faire, c'est différencier les différents types de nœuds pour leur réserver un traitement spécifique.
    J'ai des nœuds sequence_node, qui sont une suite de nœuds de différents types (j'utilise les templates variadiques pour ça). Les list_node sont un ou plusieurs nœuds du même type. Enfin, j'ai aussi des alternative_node, des optional_node et des leaf_node. Ça fait un joli modèle pour un arbre syntaxique .

    La solution d'Archi marche au poil . Mais alors… quelle bidouille ! Vivement C++0x, qu'on éclaircisse un peu nos codes.

    Encore merci !
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  12. #12
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Citation Envoyé par Florian Goo Voir le message
    Il me semble plutôt que SFINAE marche à la compilation. En fait, elle va déterminer, pour un type donné, la présence ou l'absence d'une fonction parmi l'ensemble des fonctions candidates à la résolution de la surcharge. Cette résolution, elle, se fait bien à l'exécution.
    Oui mais le changement résultant est à l'exécution.

    Boost.MPL/TypeTraits t'aideront bien si tu as des bidouilles de ce genre à faire.

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 22/04/2013, 12h07
  2. Réponses: 14
    Dernier message: 26/01/2011, 22h18
  3. Réponses: 1
    Dernier message: 12/11/2007, 13h36
  4. chemin d'acces pour classe
    Par DEVfan dans le forum C++
    Réponses: 3
    Dernier message: 16/08/2007, 08h31
  5. [états]Un trait pour séparer les clients
    Par jawed dans le forum IHM
    Réponses: 7
    Dernier message: 18/03/2007, 22h27

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