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 :

contraindre un type générique


Sujet :

Langage C++

  1. #1
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut contraindre un type générique
    Bonjour à tous.

    Je souhaite créer un module qui gère la gravité et que je pourrais réutiliser dans tous mes futurs projets. Mais je veux pouvoir faire des choses (qui pour l'instant ne me servent pas) comme faire que plusieurs éléments dans un même environnement puisse subir des lois physiques différentes.

    J'ai en tête un truc du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Gravity<Personnage> myGravity;
    Gravity<IA> myGravity2;
     
    myGravity.AddObject(J1);
    myGravity.AddObject(J2);
    for (int i=0; i< 100; i++)
       myGravity2.AddObject(IA(i));//ça ne me dérengerais pas que l'on puisse construire des objets au moment de leur ajout dans myGravity2 par exemple
    //etc...
     
    myGravity.Launch();//l'idée que ce soit en tache de fond ne me déplairait pas non plus...
    Bref, ma problématique principale, c'est comment, si j'ai une classe template Gravity<T>, contraindre mon type T à posséder des coordonnées de type (x,y) ?
    Nullius in verba

  2. #2
    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,

    1/ En laissant le compilateur lever une erreur...

    2/ Il me semble (mais peut être dis-je une bêtise) que Boost.Type trait permet de construire ses propres traits + un assert.

    3/ SFINAE pour faire de l'introspection :
    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
    35
    36
     
    #include <iostream>
     
    template<class T>
    struct test_member_x
    {
       struct yes {char c;};
       struct no {char c[2];};
     
       template<class U, int U::*> struct tst_member{};
     
       template<class U>
       static yes test_f(tst_member<U,&U::x>*);
       template<class V>
       static no test_f(...);
     
       static const bool value = sizeof(test_f<T>(0))==sizeof(yes);
    };
     
    struct one
    {
       int x;
       int y;
    };
     
    struct two
    {
    };
     
    int main()
    {
       std::cout<<std::boolalpha;
       std::cout<<test_member_x<one>::value<<"\n";
       std::cout<<test_member_x<two>::value<<"\n";
       return 0;
    }
    En passant par macro (nom et type du membre à tester), on peut généraliser test_member_x

  3. #3
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Bonjour,

    La vache je croyais pas que quelqu'un réussirait à me répondre !

    Tout d'abord merci pur votre réponse.

    3/...je vais déjà essayer de comprendre ce que vous avez fait là
    Je comprends a peu près ce que vous faites mais j'ai du mal à assembler les dernières pièces du puzzle...

    Déjà est-ce que les 3 petits points c'est une manière spécifier..."n'importe quoi"?
    Ensuite, pourquoi ce "0" dans l'évaluation ?

    Ces deux choses m'aideront je penses à finir de comprendre ce que vous m'avez proposé là, mais sinon...grandiose, franchement merci




    Sinon pur la macro, je penses que ça va pas être beau... et pour l'instant je vois même pas comment m'y prendre, chaque chose en son temps
    Nullius in verba

  4. #4
    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 Kaamui Voir le message
    Déjà est-ce que les 3 petits points c'est une manière spécifier..."n'importe quoi"?
    Les ... c'est une fonction à paramètre variadic comme printf. Elle peut de plus prendre (en théorie) n'importe quoi comme paramètre. On joue sur le fait que dans le choix de la fonction à appeler parmi les différentes disponibles, celle-ci est la moins prioritaire face à toute les autres. Donc quand le membre existe, deux fonctions sont candidates : la variadic et celle avec le pointeur sur la structure. C'est alors cette dernière qui est choisi. A contrario, lorsque le membre n'existe pas, celle avec les ... est la seule à convenir.
    On s'appuie aussi sur le SFINAE (cf F.A.Q. Qu'est ce que le SFINAE) pour que le code compile sans erreur si le membre n'existe pas quand on essaie d'y accéder dans static yes test_f(tst_member<U,&U::x>*);. Donc quand le membre n'existe pas, on se tourne vers l'autre fonction (celle avec les ...).
    Puis la taille des deux types retours pour savoir si c'est vrai ou faux.
    Citation Envoyé par Kaamui Voir le message
    Ensuite, pourquoi ce "0" dans l'évaluation ?
    Les deux fonction test_f prennent un pointeur. 0 c'est tout simplement le pointeur nul (il n'existe pas en C++03). En C++11, on aurait pu utiliser nullptr
    Ceci dit, pour ton problème, je laisserai le compilateur lever une erreur..

  5. #5
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Vous pensez que cela n'est pas utile, pour ce que je fait ?

    En tout cas, je viens encore d'apprendre des choses intéressantes,
    et je vous en remercie.


    Cordialement,
    Nullius in verba

  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
    Salut,
    Citation Envoyé par Kaamui Voir le message
    Vous pensez que cela n'est pas utile, pour ce que je fait ?
    S'il s'agit d'apprendre ces techniques, alors cela est utile.

    S'il s'agit de contraindre le type générique, alors oui, je pense que je laisserais le compilateur râler.

    Cette introspection peut servir à choisir entre différents traitements selon la présence ou non de certaines propriétés.

    Pour vérifier si un paramètre générique contient bien le membre que tu utilises ... ben le compilateur le fait déjà. Au mieux tu fais avec un static_assert un message d'erreur un peu plus lisible mais c'est même pas sur. Au pire, tu risques de n'être pas à jour au fur et à mesure de l'évolution de ton code.


    Autre chose, à la lecture des noms, je suis surpris que Gravity prenne en paramètre Personnage ou IA. Je flaire une mauvaise piste de design.

  7. #7
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Pour vérifier si un paramètre générique contient bien le membre que tu utilises ... ben le compilateur le fait déjà. Au mieux tu fais avec un static_assert un message d'erreur un peu plus lisible mais c'est même pas sur. Au pire, tu risques de n'être pas à jour au fur et à mesure de l'évolution de ton code.
    Apres moults experiences, y a deux trucs a considerer :

    - utiliser un truc genre Boost.Concept pour checker que le type verifie le Concept dont on a besoin. La SFINAE est plus utile pour la selection de surcharge que le test d'erreur.

    - utiliser la SFINAE mais pour sauter dans une fonction trampoline permettant d'eviter l'error cascading. Souvent on test avec une static_assert puis on fait le traitement. Sauf que le compilo compile tout et on a la static_assert ET les erreurs, rendant le message illisible. Donc, on utilise la SFIANE pour sauter soit dans une implementation qui ne fait que la static_assert, soit dans le vrai code.

  8. #8
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Oui c'est plus pour apprendre.


    Pour l'architecture, ce que je souhaite, c'est avoir un module dans lequel je peux intégrer un nouvel objet quand je le souhaite (pas que ce soit automatique, on sait jamais, je pourrais avoir besoin qu'un objet parmi 1000 ne subissent pas la gravité). Je peux aussi avoir besoin que différents classes "frères et sœurs" ne subissent pas les même lois physiques. D'où les exemples avec IA et Personnage.

    Le nom Gravity est peut-être un peu restrictif car il risque de remplir plus de fonctionnalités que ça si un jour il arrive à terme.

    Juste pour être sur de vous suivre, vous cous attendiez à quoi comme paramètre pour T.

    @ Joel F : j'en prend bonne note, et au moment ou je devrai faire un choix pour l'approche à ce sujet, je reviendrai lire votre réponse


    Bonne année à vous 2 au fait.

    Cordialement,
    Nullius in verba

  9. #9
    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 Kaamui Voir le message
    Juste pour être sur de vous suivre, vous cous attendiez à quoi comme paramètre pour T.
    Quelque chose de plus concrètement lié à un calcul de la gravité (un algorithme, un parametrage, une politique ...). Personnage est un élément qui est soumis à une certaine gravité. IA ???.
    Posons 2 questions simples :
    => quelle est la responsabilité de Gravity ?
    => (et pour reprendre celle de Joel) : quel est le concept de son paramètre générique ?

Discussions similaires

  1. [2.0] polymorphisme avec des types générique
    Par mister3957 dans le forum Général Dotnet
    Réponses: 3
    Dernier message: 31/05/2007, 08h11
  2. Type générique paramétré ?
    Par Lebbihi dans le forum Langage
    Réponses: 2
    Dernier message: 15/03/2007, 09h58
  3. [Framework] IOC - Type générique
    Par seawolfm dans le forum Spring
    Réponses: 1
    Dernier message: 06/02/2007, 18h17
  4. Réponses: 12
    Dernier message: 23/09/2006, 12h12
  5. y a-t-il un support de types génériques pour python ?
    Par silverhawk.os dans le forum Général Python
    Réponses: 15
    Dernier message: 24/03/2006, 18h23

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