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 :

Utilisation de enable_if


Sujet :

Langage C++

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut Utilisation de enable_if
    Hello,

    J'ai défini une classe templatisée (appelons la MaClasse) ayant sémantique de valeur. J'ai donc défini les opérateurs de comparaison.

    Si B dérive de A, j'aimerais pouvoir comparer des instances MaClasse<A> et MaClasse<B>. Je comptais donc y aller à coup de enable_if et isbase_of :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template<typename T, typename IndexType=typename T::IndexType>
    struct SafeIndex
    {
        IndexType value;
        ...
        template <class U, template <typename> class V, class = typename std::enable_if<std::isbase_of<T,U>::value>>
        friend bool operator == (const SafeIndex<T>& lhs, const SafeIndex<U>& rhs) { return lhs.value == rhs.value; }
        ...
    };
    Malheureusement, ça ne fonctionne pas : j'obtiens une erreur Visual C4519 :
    default template arguments are only allowed on a class template

    Comment faire ??

    Merci.

  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,

    A part attendre que visual studio respecte la norme, je ne vois pas vraiment comment t'y prendre (note que ce code devrait fonctionner avec Gcc )
    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 éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    C'est triste ce que tu me racontes là.

    Ça me pourrit ma conception.

  4. #4
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    752
    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 : 752
    Par défaut
    is_base_of, non ?

  5. #5
    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
    Citation Envoyé par oodini Voir le message
    C'est triste ce que tu me racontes là.

    Ça me pourrit ma conception.
    Oui, je sais bien!!!

    Ceci dit, je ne vois pas trop pourquoi tu t'inquiètes :

    Toute variation sur le thème de SafeIndex représentera, forcément, un type différent dans le sens ou SafeIndex<A> sera différent de SafeIndex<B> et que, si tu implémente l'opérateur ==, tu ne pourras de toutes manières pas comparer l'un avec l'autre

    Au pire, le static_assert est une fonctionnalité fournie par VS2012, et, sommes toutes, il pourrait sans doute être plus intéressant de l'utiliser
    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
    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
    Citation Envoyé par jo_link_noir Voir le message
    is_base_of, non ?
    Je ne sais pas où VS2012 en est au niveau du support des typetraits, mais ici, l'erreur n'est pas due à un trait non implémenté, mais bien au fait que VC++ n'accepte pas encore les paramètres template par défaut pour les fonctions.

    A partir de là, que tu essayes d'utiliser enable_if, is_base_of ou toute la panoplie des typetraits, dés le moment où tu envisageras d'utiliser une valeur par défaut pour le paramètre template d'une fonction, tu te feras jeter sans rémission possible
    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

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Toute variation sur le thème de SafeIndex représentera, forcément, un type différent dans le sens ou SafeIndex<A> sera différent de SafeIndex<B> et que, si tu implémente l'opérateur ==, tu ne pourras de toutes manières pas comparer l'un avec l'autre
    Si B dérive de A, et que j'ai un vecteur de A*, j'aimerais que l'indice des éléments (que je sauvegarde dans des variables sous forme de SafeIndex<A> et SafeIndex<B>) soient comparables. Surtout si je dois mettre ces variables dans un tableau pour définir un sous-ensemble.

  8. #8
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    752
    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 : 752
    Par défaut
    J'ai cru lire comme erreur que le paramètre de template n'était pas valide (allez savoir ou j'ai pêcher ça Oo).

    L'histoire du tableau de SafeIndex<A> et SafeIndex<B> me semble bancal, mettre 2 types différents dans un même tableau va devenir compliquer. possible que je rate quelque chose.

    Concernant le paramètre par défaut, on peut le déplacer au niveau du type de retour.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    template <class U, template <typename> class V, class = typename std::enable_if<std::isbase_of<T,U>::value>>
    friend typename std::enable_if<std::isbase_of<T,U>::value, bool>::type
    operator == (const SafeIndex<T>& lhs, const SafeIndex<U>& rhs) {...}
    (il sers à quoi le V dans tous ça ?)

  9. #9
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par jo_link_noir Voir le message
    Concernant le paramètre par défaut, on peut le déplacer au niveau du type de retour.
    Et ça permet de passer outre la limitation de VS (limitation levée dans le CTP de novembre, si utilisable).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template<typename T, typename IndexType=typename T::IndexType>
    struct SafeIndex
    {
    	IndexType value;
    	template <class U>
    	friend typename std::enable_if< std::is_base_of<T, U>::value || std::is_base_of<U, T>::value, bool>::type
    	operator==(const SafeIndex<T>& lhs, const SafeIndex<U>& rhs) {
    		return lhs.value == rhs.value;
    	}
    };
    Je sais pas si le fait de tester is_base_of<T, U> dans ce sens seulement est voulu ou un oubli.

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par jo_link_noir Voir le message
    L'histoire du tableau de SafeIndex<A> et SafeIndex<B> me semble bancal, mettre 2 types différents dans un même tableau va devenir compliquer. possible que je rate quelque chose.
    J'ai essayé de trouver un exemple à l'arrache...
    Toujours est-il que ça a du sens pour moi de comparer les deux types (pas en théorie ; en pratique).

    Citation Envoyé par jo_link_noir Voir le message
    Concernant le paramètre par défaut, on peut le déplacer au niveau du type de retour.
    Non. On ne peut pas, quand on surcharge un opérateur de comparaison, qui doit renvoyer un bool.

    Citation Envoyé par jo_link_noir Voir le message
    (il sers à quoi le V dans tous ça ?)
    Je ne sais plus.

  11. #11
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    Je sais pas si le fait de tester is_base_of<T, U> dans ce sens seulement est voulu ou un oubli.
    Ni l'un ni l'autre.
    Disons que je n'avais pas été jusqu'à ce point, vu que le cas simple ne compilait pas (je marche sur des œufs, dans ce genre de codage).

  12. #12
    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
    Sinon, il te reste toujours une autre solution...

    Vu que tu ne peux pas (encore) donner de valeur par défaut, arrange toi pour fournir un flag qui fera le travail

    Par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    template<typename T, typename IndexType=typename T::IndexType>
    struct SafeIndex
    {
            using template <U>tag = typename std::is_base_of<T,U>::type;
    	IndexType value;
            bool compare(const SafeIndex<T>& lhs, const SafeIndex<U>& rhs,
                         std::true_type const &) {
    		return lhs.value == rhs.value;
    	}
            bool operator==(const SafeIndex<T>& lhs, const SafeIndex<U>& rhs){
                return compare(lhs,rhs,tag());
            }
    };
    (code non testé, mais l'idée est là

    voir, si le static_assert fonctionne, quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template<typename T, typename IndexType=typename T::IndexType>
    struct SafeIndex
    {
    	IndexType value;
            template <typename U>
            bool operator==(const SafeIndex<T>& lhs, const SafeIndex<U>& rhs){
                static_assert(std::is_base_of<T,U>::value,
                             "T type should be a base class for U");
                return compare(lhs,rhs,tag());
            }
    };
    L'idée étant d'obtenir une erreur de compilation si tu essayes, définitivement, de comparer deux éléments qui n'ont pas une base commune (la solution à base de static_assert, bien que non testée, ayant quand meme de fortes chances de provoquer une erreur de compilation plus lisible que la première proposée )
    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

  13. #13
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par oodini Voir le message
    Non. On ne peut pas, quand on surcharge un opérateur de comparaison, qui doit renvoyer un bool.
    typename std::enable_if<Condition, bool>::type est un typedef sur bool si Condition est vrai, le fait de devoir renvoyer un bool ne pose pas de problème ? A moins que quelque chose m’échappe.

  14. #14
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    @koala01 : à tester ; la lisibilité du code en prend un coup, toutefois

    @Iradrille : je ne vois pas le rapport entre le type de retour de l'opérateur == et le type du typedef de enable_if

  15. #15
    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
    Citation Envoyé par oodini Voir le message
    @koala01 : à tester ; la lisibilité du code en prend un coup, toutefois
    A quel niveau la lisibilité en prend-elle un coup

    La première solution ne fait qu'appliquer un principe que l'on utilise régulièrement pour l'opérateur << (à savoir appeler une fonction (souvent virtuelle) pour faire le travail )

    La deuxième solution permet carrément d'avoir un message d'erreur sans doute beaucoup plus clair que celui qui nous serait renvoyé par le compilateur en nous basant sur le enable_if
    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

  16. #16
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    VS2013 apparamment permet les arguments templates par defaults avec les fonctions. J'ai pas teste encore mais c'est dans la liste des features C++ implementes.

    Le passage de VS2012 a VS2013 est plutot simple dans mon experience (j'ai tente voir avant hier), a part bien sur que les extensions qui ont pas encore ete upgrade. Apres tout c'est qu'une RC.

  17. #17
    Invité de passage
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 1
    Par défaut
    Citation Envoyé par oodini Voir le message
    @Iradrille : je ne vois pas le rapport entre le type de retour de l'opérateur == et le type du typedef de enable_if
    Ce que dit Iradrille est correct, utiliser le typedef de enable_if au niveau du type de retour fonctionne très bien avec VS2012 (peut-être même le 2010).
    Le fonctionnement est similaire à ce que tu veux faire. Si la condition du enable_if est vrai alors le "typedef type" est défini sinon il ne l'est pas et donc ta fonction n'a pas de type de retour ce qui engendre une erreur de compilation.

    Tu peux voir les 2 utilisations de enable_if sur http://www.cplusplus.com/reference/t...its/enable_if/

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

Discussions similaires

  1. utiliser les tag [MFC] [Win32] [.NET] [C++/CLI]
    Par hiko-seijuro dans le forum Visual C++
    Réponses: 8
    Dernier message: 08/06/2005, 15h57
  2. Réponses: 4
    Dernier message: 05/06/2002, 14h35
  3. utilisation du meta type ANY
    Par Anonymous dans le forum CORBA
    Réponses: 1
    Dernier message: 15/04/2002, 12h36
  4. [BCB5] Utilisation des Ressources (.res)
    Par Vince78 dans le forum C++Builder
    Réponses: 2
    Dernier message: 04/04/2002, 16h01
  5. Réponses: 2
    Dernier message: 20/03/2002, 23h01

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