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 :

Detection automatique de type : quelques trucs


Sujet :

C++

  1. #1
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Points : 2 548
    Points
    2 548
    Par défaut Detection automatique de type : quelques trucs
    voila, je me suis correctement cassé la tête sur le sujet de la détection de type. En effet, lorsque l'on pratique la métaprogramation, le typage de certains éléments nous est inconnus.

    Un bout de code vaut mieux qu'on long discours :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template<class A, class B> type? doSomething(A a, B b){
       return a+b;
    }
    On notera que a et b ne sont pas forcement du même type et que a+b peut être de n'importe quel type en fonction de la surcharge de l'opérateur +.

    Nous allons donc utiliser quelque chose de bien peu catholique : typeof. Il faut noter ici que typeof est une extension qui n'est pas supportée par tout les compilateurs. Elle fonctionne notamment avec gcc et Xl (compilo d'IBM).

    Comment typeof prend en paramètre une expression quelconque et se substitue a son type. On pourrait donc réécrire notre code comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template<class A, class B> __typeof__(A()+B()) doSomething(A a, B b){
       return a+b;
    }
    mais cela suppose que A et B aient des constructeur par défaut, ce qui n'est pas forcement le cas. Il nou faut donc chercher a contourner cette contrainte. Nous allons chercher a obtenir un objet d'un type de notre choix sans avoir à l'instancier.

    Attention les enfant, n'essayer jamais d'utiliser la suite autrement que pour la détection automatique de type, il peut en résulter de graves failles de sécurité dans votre programme, ainsi que mener a des plantages.

    Nous allons tout d'abord faire une classe qui permet de récupérer notre objet de type quelconque sans l'instancier. pour cale, nous allons faire des manœuvres d'un gout douteux avec des pointeurs.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    template<class T> class falsePtr{
       falsePtr(){}
       T*e;
       T& operator*(){ return *e; }
       T& operator[](int i){ return e[i] }
       const T& operator*() const { return *e; }
       const T& operator[](int i) const { return e[i] }
    };
     
    //Et une belle fonction pour récupérer notre objet :
    template<class T> T& getObj(){
       return *(falsePtr<T>());
    }
    Bien sur, il est exclu d'utiliser tout ca pour autre chose que la détection de type !

    Voila ce qu'on obtient si l'on reprend notre exemple ci-dessus :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template<class A, class B> __typeof__(getObj<A>()+getObj<B>()) doSomething(A a, B b){
       return a+b;
    }
    Et voila le travail. C'est pas exactement ce que j'appelle du code propre, mais ca a le mérite de très bien fonctionner. En espérant que ça en aide certains

    ATTENTION : Ne générez pas de recherche de type circulaire sans quoi vous obtiendrez des erreurs interne du compilateur pour gcc, ce qui est gênant et pas facile a débugguer

    Voici en images ce qu'il ne faudrait pas faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template<class A, class B> __typeof__(doSometing(getObj<A>(),getObj<B>())) operator+(A a, B b){
       return a+b;
    }
    Voila, vous savez faire du typage automatique en C++ !

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    La syntaxe C++0x pour écrire cela est quelque chose du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename A, typename B>
    auto doSomething(const A& a, const B& b) -> decltype(a + b)
    {
        return a + b;
    }
    Cependant, la meilleure solution que l'on peut écrire pour l'instant c'est ceci (fonctionne avec GCC 4.3)
    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 T>
    T& make()
    {
         return *(T*)0;
    }
     
    template<typename A, typename B>
    struct doSomething_type
    {
        typedef __decltype__(make<A>() + make<B>()) type;
    };
     
    template<typename A, typename B>
    typename doSomething_type<A, B>::type doSomething(const A& a, const B& b)
    {
        return a + b;
    }
    typeof n'est pas la même chose que decltype. typeof ne retourne pas le type réel des expressions car il en enlève les références.

    Ensuite, le code que tu donnes ne devrait pas compiler avec GCC. GCC n'a pas défini d'ABI pour les fonctions templates dont la valeur de retour dépend de typeof ou decltype.
    Cela génére normalement une erreur dans mangle.c
    L'astuce pour contourner ce problème consiste à passer par une méta-fonction intermédiaire.
    Boost ftw

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Points : 2 548
    Points
    2 548
    Par défaut
    Si, le code fournis fonctionne parfaitement. Pour ce qui est du tye auto, j'étais au courant, mais ca reste pour l'instant une norme et les compilos ne savant pas encore traiter ce genre de choses.

    Merci pour cette précision sur la différence entre __typeof__ et __decltype__ que j'ignorais.

    EDIT: apres quelques tests, il semblerait que decltype soit bien moins souple dans son utilisation que __typeof__ . En effet decltype n'aime pas du tout qu'on fasse des appels de fonction. Ce qui est très dommage.

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Si, le code fournis fonctionne parfaitement.
    Non, il ne fonctionne pas.
    Quand tu instancies ta fonction template, tu as une erreur de GCC dans cp/mangle.c (dans les versions récentes ça dit carrément "sorry, mangling typeof unimplemented"), parce qu'il n'y a pas d'ABI pour typeof ou decltype. C'est un bug connu qui n'est absolument pas réglé.

    Je viens de remarquer que __decltype__ ne se comporte pas comme decltype. Normalement ça peut très bien s'utiliser comme valeur de retour, bien entendu, mais ça ne semble marcher que pour decltype et pas pour __decltype__.
    Bien sûr, on a aussi un message d'erreur "sorry, unimplemented: cannot be mangled due to a defect in the C++ ABI"
    Boost ftw

  5. #5
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Points : 2 548
    Points
    2 548
    Par défaut
    J'ai bien été confronté a des erreurs dans cp/mangle.c, mais pas a tous les coups (j'ai d'ailleurs aucuné idée des conditions pour que ça se produise ou non).

    je passe de toute façon maintenant toujours par des structure du type

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template<class T, class U> struct machinTrucTypeDetector {
       typedef type getType;
    };
    Qui est bien plus souple et plus lisible au final quand on manipule des types complexes.

    C'est étrange cette différence entre decltype et __decltype__ . . .

    En tous cas tes bouts de code m'ont donné de bonne idée et tu m'as bien éclairé sur le sujet. je sais pas si c'est moi qui avait mal cherché, mais les infos sont difficiles a trouver sur le sujet sur le net.

  6. #6
    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
    De toute manière, la seule manière de franchir correctement l'erreur de manière portable est celle exposée par loufoque : une classe de traits.

Discussions similaires

  1. Detecter automatiquement le lecteur de CD
    Par jean-paul lepetit dans le forum VB.NET
    Réponses: 16
    Dernier message: 17/10/2007, 16h31
  2. Réponses: 4
    Dernier message: 22/11/2006, 13h07
  3. Quelques trucs que je ne comprends pas
    Par darkbob dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 30/10/2006, 10h15
  4. Detection automatique de fonte
    Par HNT dans le forum Général Conception Web
    Réponses: 6
    Dernier message: 16/10/2005, 18h16
  5. GEstion des types! Besoin d'aide il me manque quelques trucs
    Par popogendarme dans le forum PostgreSQL
    Réponses: 6
    Dernier message: 03/02/2005, 18h56

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