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 :

[C++11] Convertir un int en une constexpr.


Sujet :

Langage C++

  1. #1
    Invité
    Invité(e)
    Par défaut [C++11] Convertir un int en une constexpr.
    Salut,

    Je voudrais convertir un int en un constexpr int car j'ai une fonction virtuelle et elle ne peut pas retourner une constexpr.

    J'ai cherché par tout les moyens ce qui me résulte à chaque fois en une erreur de compilation :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    template <typename I>
        constexpr int intToConstExpr(I expr, const int value) const {
            if (expr != value)
                return intToConstExpr(expr+1, value);
            return expr;
        }

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    constexpr int cmpt = intToConstExpr(0, getType());

    La fonction getType() retourne juste un entier qui me sert d'identifiant pour un type d'objet dérivé.

    Voici l'erreur de compilation :

    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    ||=== Build: Debug in ODFAEG (compiler: GNU GCC Compiler) ===|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingVolume.h|38|error: ‘constexpr int odfaeg::BoundingVolume<D>::intToConstExpr(I, int) const [with I = int; D = odfaeg::BoundingBox]’ called in a constant expression|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingVolume.h|100|note: ‘constexpr int odfaeg::BoundingVolume<D>::intToConstExpr(I, int) const [with I = int; D = odfaeg::BoundingBox]’ is not usable as a constexpr function because:|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingVolume.h|100|error: enclosing class of constexpr non-static member function ‘constexpr int odfaeg::BoundingVolume<D>::intToConstExpr(I, int) const [with I = int; D = odfaeg::BoundingBox]’ is not a literal type|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingVolume.h|35|note: ‘odfaeg::BoundingVolume<odfaeg::BoundingBox>’ is not literal because:|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingVolume.h|35|note:   ‘odfaeg::BoundingVolume<odfaeg::BoundingBox>’ has a non-trivial destructor|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingVolume.h|39|error: no matching function for call to ‘get(std::tuple<odfaeg::BoundingBox*>&)’|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingVolume.h|39|note: candidates are:|
    /usr/include/c++/4.8/utility|142|note: template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&)|
    /usr/include/c++/4.8/utility|142|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/utility|147|note: template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(std::pair<_Tp1, _Tp2>&&)|
    /usr/include/c++/4.8/utility|147|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/utility|152|note: template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&)|
    /usr/include/c++/4.8/utility|152|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/array|268|note: template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr _Tp& std::get(std::array<_Tp, _Nm>&)|
    /usr/include/c++/4.8/array|268|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/array|277|note: template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr _Tp&& std::get(std::array<_Tp, _Nm>&&)|
    /usr/include/c++/4.8/array|277|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/array|285|note: template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr const _Tp& std::get(const std::array<_Tp, _Nm>&)|
    /usr/include/c++/4.8/array|285|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/tuple|757|note: template<long unsigned int __i, class ... _Elements> constexpr typename std::__add_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(std::tuple<_Elements ...>&)|
    /usr/include/c++/4.8/tuple|757|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/tuple|764|note: template<long unsigned int __i, class ... _Elements> constexpr typename std::__add_c_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(const std::tuple<_Elements ...>&)|
    /usr/include/c++/4.8/tuple|764|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/tuple|771|note: template<long unsigned int __i, class ... _Elements> constexpr typename std::__add_r_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(std::tuple<_Elements ...>&&)|
    /usr/include/c++/4.8/tuple|771|note:   template argument deduction/substitution failed:|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingVolume.h|40|error: no matching function for call to ‘get(std::tuple<odfaeg::BoundingBox*>&)’|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingVolume.h|40|note: candidates are:|
    /usr/include/c++/4.8/utility|142|note: template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&)|
    /usr/include/c++/4.8/utility|142|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/utility|147|note: template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(std::pair<_Tp1, _Tp2>&&)|
    /usr/include/c++/4.8/utility|147|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/utility|152|note: template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&)|
    /usr/include/c++/4.8/utility|152|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/array|268|note: template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr _Tp& std::get(std::array<_Tp, _Nm>&)|
    /usr/include/c++/4.8/array|268|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/array|277|note: template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr _Tp&& std::get(std::array<_Tp, _Nm>&&)|
    /usr/include/c++/4.8/array|277|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/array|285|note: template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr const _Tp& std::get(const std::array<_Tp, _Nm>&)|
    /usr/include/c++/4.8/array|285|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/tuple|757|note: template<long unsigned int __i, class ... _Elements> constexpr typename std::__add_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(std::tuple<_Elements ...>&)|
    /usr/include/c++/4.8/tuple|757|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/tuple|764|note: template<long unsigned int __i, class ... _Elements> constexpr typename std::__add_c_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(const std::tuple<_Elements ...>&)|
    /usr/include/c++/4.8/tuple|764|note:   template argument deduction/substitution failed:|
    /usr/include/c++/4.8/tuple|771|note: template<long unsigned int __i, class ... _Elements> constexpr typename std::__add_r_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(std::tuple<_Elements ...>&&)|
    /usr/include/c++/4.8/tuple|771|note:   template argument deduction/substitution failed:|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingVolume.h||In instantiation of ‘odfaeg::BoundingVolume<D>* odfaeg::BoundingVolume<D>::clone() [with D = odfaeg::BoundingBox]’:|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/boundingBox.cpp|261|required from here|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingVolume.h|78|warning: no return statement in function returning non-void [-Wreturn-type]|
    Voila donc je voudrais savoir si il y a moyen de convertir un int en une constexpr.

  2. #2
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Il y a un moyen assez violent si ton n est petit.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    template<int i>
    constexpr int f(int n)
    {
        return n==0 ? (i) : (f<i+1>(n-1));
    }
     
    template<>
    constexpr int f<899>(int n) // par défaut, gcc n’étend pas au-delà de 900
    {
        return 0;
    }
    Néanmoins, je ne recommanderai pas cette technique, sauf pour des cas ultra-particuliers et bien bornés. Ça va générer une quantité de code absolument astronomique et sera probablement complètement sous-optimal au final.

    Tu ne peux vraiment pas te passer d’une constexpr ?

  3. #3
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Le problème de base, c'est que constexpr désigne une expression dont la valeur est connue à la compilation, et que <pas constexpr> une expression dont ce n'est pas le cas.

    En résumé, tu dis au compilateur: "Définis ce bidule dont tu connaitras la valeur à partir de cet autre bidule dont tu ne connais pas la valeur."

    Ça n'a pas de sens en français, ça ne peut pas en avoir en C++ non plus.

    Il n'y a que deux solutions: changer l'une ou l'autre des parties du problème
    1. Ou bien supprimer le constexpr à gauche
    2. Ou bien transformer la partie droite en constexpr


    La première solution, c'est abandonner le problème ici pour le rencontrer plus en aval du code
    La seconde, c'est faire remonter le problème plus en amont.

    Dans ce second cas, il faut que getType soit une constexpr
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  4. #4
    Invité
    Invité(e)
    Par défaut
    Ha mer de, ma fonction getType() est virtuelle dont elle ne peut pas retourner une constexpr....

    Et j'ai absolument besoin d'un constxpr car la fonction std::get attend une constexpt pour récupérer l'élément y d'un tuple :
    Citation Envoyé par white_tentacle Voir le message
    Il y a un moyen assez violent si ton n est petit.

    ...

    Néanmoins, je ne recommanderai pas cette technique, sauf pour des cas ultra-particuliers et bien bornés. Ça va générer une quantité de code absolument astronomique et sera probablement complètement sous-optimal au final.

    Tu ne peux vraiment pas te passer d’une constexpr ?
    Je ne pense pas que un jour j'aie une classe de base qui possède 900 classes dérivées, donc, je pense que je peux minimiser n à 10 se sera déjà bien. (Au lieu de 899)
    Dernière modification par Invité ; 30/07/2014 à 16h18.

  5. #5
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    alors la, c'est plus "simple", parce que ton cas est limité.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <type bien choisi> get(tuple, type) {
        switch(type) {
        case 1 : return tuple.get<1>();
        case 2 : return tuple.get<2>();
    ...
        }
    }
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  6. #6
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Si je comprends bien, tu utilises le n renvoyé par ta classe pour récupérer le type effectif dans une typelist ?

    La question, c’est qui détient cette typelist ? J’ai fait un truc un peu du genre dernièrement, et j’ai trouvé qu’il était finalement plus simple que la typelist soit dans la classe de base (oui, c’est conceptuellement gênant, mais le gain que ça m’apporte vaut cette concession), que de recourir à des artifices (déjà que là, ce n’est pas simple).

    La technique que j’avais employée pour « borner », si ça peut te donner des idées :

    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
    37
     
    template<typename T, int i, bool>
    struct S
    {
     
    };
     
    template<>
    template<typename T, int i>
    struct S<T, i, false>
    {
        static void get(int, T& result)
        {
            assert(false);
        }
    };
     
    template<>
    template<typename T, int i>
    struct S<T, i, true>
    {
        static void get(int n, T& result)
        {
            switch(n)
            {
                case 0:
                {
                    // initialize result with something
                    break;
                }
                default:
                    constexpr bool isGreater = std::tuple_size<typename T::inheritedTypes>::value > i + 1;
                    S<T, i+1, isGreater>::get(n-1, result);
                    break;
            }
        }
    };
    Le is_greater va permettre de limiter l’instanciation des templates à seulement les cas nécessaires pour gérer la typelist. Si on appelle avec n trop grand, on aura une assertion au runtime (liée à une violation de précondition), ce qui n’est pas un problème puisque c’est un bug dans le code.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Oui j'essaye de faire une typelist, et de mettre celle-ci dans la classe de base.

    Et je voudrais utiliser le n renvoyé par la classe dérivée pour récupérer le type dans la typeliste.

    Comme les types des classes dérivée sont différent je pensais faire ceci dans la classe de base :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::tuple<Derived1*, Dervied2*, ....> typelist;
    Et remplir le tuple à l'aide du constructeur de la classe de base, la classe de base est template vu que j'utilise le pattern CRTP, je peux donc ajouté le type dans le tuple.


    Pour récupérer le type de la classe dérivée je pensais faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::get<getN()>(typelist);
    Seulement ça ne marche pas car le problème est que j'ai besoin d'une fonction virtuelle pour récupérer le n de la classe dérivée à partir du pointeur sur l'objet de base et je ne peux pas le faire car une fonction virtuelle ne peux pas renvoyer une expression constante et donc, je peux pas récupérer n...

    Alors je cherche un autre moyen là, je ne connais pas ta méthode personnellement, il faudrait que je l'essaye.
    Dernière modification par Invité ; 30/07/2014 à 17h23.

  8. #8
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par Lolilolight Voir le message
    Oui j'essaye de faire une typelist, et de mettre celle-ci dans la classe de base.

    Et je voudrais utiliser le n renvoyé par la classe dérivée pour récupérer le type dans la typeliste.

    Comme les types des classes dérivée sont différent je pensais faire ceci dans la classe de base :

    std::tuple<Derived1*, Dervied2*, ....> typelist;
    Si tu as juste besoin des types, pas besoin de mettre les *

    Et remplir le tuple à l'aide du constructeur de la classe de base, la classe de base est template vu que j'utilise le pattern CRTP, je peux donc ajouté le type dans le tuple.
    Pas besoin de remplir ton tuple si tu utilises uniquement l’information de type. Par contre, je ne vois pas le rapport avec CRTP.

    Pour récupérer le type de la classe dérivée je pensais faire ceci :

    std::get<getN()>(typelist);
    Pour récupérer le type, utilise plutôt

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    typedef typename std::tuple_element<i,types>::type actualType;
    Tu as toujours besoin d’une constexpr, mais std::get te donnera une instance, std::tuple_element te donnera bien un type.

    Seulement ça ne marche pas car le problème est que j'ai besoin d'une fonction virtuelle pour récupérer le n de la classe dérivée à partir du pointeur sur l'objet de base et je ne peux pas le faire car une fonction virtuelle ne peux pas renvoyer une expression constante et donc, je peux pas récupérer n...

    Alors je cherche un autre moyen là, je ne connais pas ta méthode personnellement, il faudrait que je l'essaye.
    En fait il faut bien voir que le type de l’expression std::get<n>(typelist) dépend de n, ce qui fait qu’il faut « t’arranger » pour que le code soit différent quand n est différent. Du coup, généralement, on va utiliser des constructions plutôt comme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template<int n>
    void f(T& data)
    {
        data = std::get<n>(typelist);
    }
    En mixant avec ce que j’ai déjà écrit, l’idée serait de faire un appel de la sorte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    S<Base, 0, true>::get(getN(), object);
    L’appel à S va « dérouler » jusqu’à ce qu’on tombe soit sur le cas « false » (si getN renvoie un entier supérieur à la taille du tuple), soit sur le cas n == 0, où le traitement peut être effectué avec du coup un std::get<i>() qui est connu à la compilation (avec i == getN() !).

  9. #9
    Invité
    Invité(e)
    Par défaut
    Salut, j'ai essayer ça : (en asseyant de stocker le type dans tuple_element mais ça ne marche pas.
    Code cpp : 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
     
    /**
      *\namespace odfaeg
      * the namespace of the Opensource Development Framework Adapted for Every Games.
      */
    template <typename T, int i, bool>
    struct S {
    };
    template<>
    template<typename T, int i>
    struct S<T, i, false>
    {
        static void get(int n, T& result)
        {
            //assert(false);
        }
    };
    template <typename T, int i>
    struct S<T, i, true> {
        static void get(int n, T& result) {
            switch(n) {
                case 0 : {
                    actualType = std::get<i>(T::typelist);
                    break;
                }
                    default : {
                    constexpr bool isGreater = (std::tuple_size<decltype(T::typelist)>::value > i + 1);
                    S<T, i+1, isGreater>::get(n-1, result);
                    break;
                }
            }
        }
        public :
        static typename std::tuple_element<i,decltype(T::typelist)>::type actualType;
    };

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    S<BoundingVolumeBase, 0, true>::get(getType(), *other->children[i]);
    intersects(dynamic_cast<BoundingVolume<S<BoundingVolumeBase, 0, true>::actualType>>(other->children[i]));

    Il me dit expected a type, got actualType, pourtant actualType c'est un type non ?

    Sinon ton assert(false) ne compile pas.

    Sinon j'ai trois classe (BoudingVolumeBase) qui est rien d'autre qu'un type générique me servant à stocker tout les volumes englobant dans un std::vector, j'ai une autre classe template BoundingVolume<D> héritant de BoundingVolumeBase qui me sert juste à appeler la bonne méthode intersect suivant le type de volume englobant passé en paramètre à la fonction intersects, et enfin j'ai une classe BoundingBox qui dérive de BoundingVolume<D>.

    J'ai besoin de récupérer les types des volumes englobants enfant du volume englobant parent pour pouvoir appeler la bonne méthode intersects et c'est là que je n'y arrive pas. :/

    Je suis toujours obligé de faire un if pour le cast :
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    if (other->children[i]->getType() == "BoundingBox")
          if (intersects(dynamic_cast<BoundingVolume<BoundingBox>*>(other->children[i])))
                return true;
    mais en fait je voudrais enlever ce if ainsi si je rajoute un nouveau type de volume englobant, je n'ai pas besoin de modifier la classe BoundingVolume en rajoutant un if.

    Et puis je vois mal l'utilisateur de la librairie modifier le code de la librairie si il veut rajouté un nouveau type de volume. (Ca ne serait pas très pratique)

    J'ai déjà regardé du côté du pattern visitor mais, même problème.

    Le seul truc que j'ai trouvé est ce lien qui pourrait peut être m'aider : Ici

    Mais bon si y'a moyen de le faire sans rajouté toutes ses classes pour les métas-données se serait bien.
    Dernière modification par Invité ; 30/07/2014 à 20h11.

  10. #10
    Invité
    Invité(e)
    Par défaut
    Ca y est ça compile enfin!!!

    Code cpp : 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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
     
    #ifndef ODFAEG_BOUNDING_VOLUME_HPP
    #define ODFAEG_BOUNDING_VOLUME_HPP
    #include "../Core/boost/serialization/access.hpp"
    #include "../Math/vec4.h"
    #include <string>
    #include <fstream>
    #include <tuple>
    #include "../Core/tuple.h"
     
     
    /**
      *\namespace odfaeg
      * the namespace of the Opensource Development Framework Adapted for Every Games.
      */
    template <typename T, int i, bool>
    struct S {
    };
    template<>
    template<typename T, int i>
    struct S<T, i, false>
    {
        static void get(int n, T& result)
        {
            //assert(false);
        }
    };
    template <typename T, int i>
    struct S<T, i, true> {
        static void get(int n, T& result) {
            switch(n) {
                case 0 : {
     
                    break;
                }
                    default : {
                    constexpr bool isGreater = (std::tuple_size<decltype(T::typelist)>::value > i + 1);
                    actualType = std::get<i>(T::typelist);
                    S<T, i+1, isGreater>::get(n-1, result);
                    break;
                }
            }
        }
        public :
        static typename std::tuple_element<i,decltype(T::typelist)>::type actualType;
    };
     
    namespace odfaeg {
    /**
      * \file boundingVolume.h
      * \class BoudingVolume
      * \brief Manage a bounding volume for collision detection
      * \author Duroisin.L
      * \version 1.0
      * \date 1/02/2014
      *
      * Base class of all bouding volumes of the framework used for collision detection.
      *
      */
    class BoundingBox;
    class BoundingVolumeBase {
        public :
        virtual int getType() = 0;
        static std::tuple<BoundingBox*> typelist;
    };
     
    template <typename D>
    class BoundingVolume : public BoundingVolumeBase {
    public :
        BoundingVolume ()  {
     
        }
        void addChild(BoundingVolume<D>* bv) {
            children.push_back(bv);
        }
        template <typename C>
        bool intersects(BoundingVolume<C>& other) {
            //if(dynamic_cast<C&>(other)) {
                if (children.size() == 0 && other.children.size() == 0) {
                    return intersects(dynamic_cast<C&>(other));
                }  else if (children.size() == 0 && other.children.size() != 0) {
                      for (unsigned int i = 0; i < other.children.size(); i++) {
                          /*if (other->children[i]->getType() == "BoundingBox")
                              if (intersects(dynamic_cast<BoundingVolume<BoundingBox>*>(other->children[i])))
                                    return true;*/
                           //if (dynamic_cast<BoundingVolume<decltype(std::get<1>(other->children[i]->types))>*>(other->children[i])) {
                                /*BoundingVolumeBase* bv = other->children[i];
                                if (intersects(dynamic_cast<BoundingVolume<decltype(*std::get<bv->getTypeAsConst()>(typelist))>*>(other->children[i])))
                                    return true;*/
                           //}
     
                           S<BoundingVolumeBase, 0, true>::get(getType(), *other.children[i]);
                           intersects(dynamic_cast<BoundingVolume<decltype(*S<BoundingVolumeBase, 0, true>::actualType)>&>(*other.children[i]));
                      }
                } /*else {
                    for (unsigned int i = 0; i < children.size(); i++) {
                        if (other->children.size() == 0) {
                            if (children[i]->getType() == "BoundingBox")
                                if (static_cast<BoundingVolume<BoundingBox>*>(children[i])->intersects(static_cast<BoundingVolume<C>*>(other)))
                                    return true;
     
                        } else {
                            for (unsigned j = 0; j < other->children.size(); j++) {
                                if (children[i]->getType() == "BoundingBox" && other->children[i]->getType() == "BoundingBox")
                                    if (static_cast<BoundingVolume<BoundingBox>*>(children[i])->intersects(static_cast<BoundingVolume<BoundingBox>*>(other->children[j])))
                                        return true;
                            }
                        }
                    }
                }*/
            //}
            return false;
        }
        virtual BoundingVolume<D>* clone() {
        }
        virtual bool intersects (BoundingBox &other) {
            return false;
        }
        virtual Vec3f getPosition() {
            return Vec3f(0, 0, 0);
        }
        virtual Vec3f getSize() {
            return Vec3f(0, 0, 0);
        }
        virtual Vec3f getCenter() {
            return Vec3f(0, 0, 0);
        }
        virtual void move (Vec3f t) {
        }
        std::vector<BoundingVolumeBase*> getChildren() {
            return children;
        }
        virtual int getType() = 0;
        virtual ~BoundingVolume() {}
    public :
        std::vector<BoundingVolumeBase*> children;
    };
    }
    #endif // BOUNDING_AREAS

    Par contre je sais pas si ça marchera à l'exécution.

    Maintenant il ne me reste plus qu'à trouver un moyen pour que le développeur puisse définir lui même la type liste. (Ou bien qu'elle soit définie automatiquement) si le développeur veut créer ses propres types de volumes englobant.

    Mais ça je vois pas trop comment faire là encore.

  11. #11
    Invité
    Invité(e)
    Par défaut
    Ha cette fois ci je pense que c'est bon!!! (J'ai trouvé)

    En fait il suffisait d'utiliser std::tuple_cat.

    Il y a juste que je peux pas appeler std::get sur un tuple vide donc je dois ajouté un type bidon dans la type liste comme premier élément pour mon tuple mais c'est pas grâve, j'espère que je n'airai pas de plantage à l'exécution :

    Code cpp : 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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
     
    #ifndef ODFAEG_BOUNDING_VOLUME_HPP
    #define ODFAEG_BOUNDING_VOLUME_HPP
    #include "../Core/boost/serialization/access.hpp"
    #include "../Math/vec4.h"
    #include <string>
    #include <fstream>
    #include <tuple>
    #include "../Core/tuple.h"
     
     
    /**
      *\namespace odfaeg
      * the namespace of the Opensource Development Framework Adapted for Every Games.
      */
    template <typename T, int i, bool>
    struct S {
    };
    template<>
    template<typename T, int i>
    struct S<T, i, false>
    {
        static void get(int n, T& result)
        {
            //assert(false);
        }
    };
    template <typename T, int i>
    struct S<T, i, true> {
        static void get(int n, T& result) {
            switch(n) {
                case 0 : {
                    actualType = std::get<i>(T::typelist);
                    break;
                }
                    default : {
                    constexpr bool isGreater = (std::tuple_size<decltype(T::typelist)>::value > i + 1);
                    S<T, i+1, isGreater>::get(n-1, result);
                    break;
                }
            }
        }
        public :
        static typename std::tuple_element<i,decltype(T::typelist)>::type actualType;
    };
     
    namespace odfaeg {
    /**
      * \file boundingVolume.h
      * \class BoudingVolume
      * \brief Manage a bounding volume for collision detection
      * \author Duroisin.L
      * \version 1.0
      * \date 1/02/2014
      *
      * Base class of all bouding volumes of the framework used for collision detection.
      *
      */
    class BoundingBox;
    class BoundingVolumeBase {
        public :
        template <typename D> BoundingVolumeBase(D* type) {
            if (std::tuple_size<decltype(typelist)>::value <= type->getType()) {
                std::tuple<D*> tp = std::make_tuple(type);
                std::tuple_cat(typelist, tp);
            }
        }
        virtual int getType() = 0;
        static std::tuple<BoundingBox*> typelist;
    };
     
    template <typename D>
    class BoundingVolume : public BoundingVolumeBase {
    public :
        BoundingVolume () : BoundingVolumeBase(new D()) {
     
        }
        void addChild(BoundingVolume<D>* bv) {
            children.push_back(bv);
        }
        template <typename C>
        bool intersects(BoundingVolume<C>& other) {
            //if(dynamic_cast<C&>(other)) {
                if (children.size() == 0 && other.children.size() == 0) {
                    return intersects(dynamic_cast<C&>(other));
                }  else if (children.size() == 0 && other.children.size() != 0) {
                      for (unsigned int i = 0; i < other.children.size(); i++) {
                          /*if (other->children[i]->getType() == "BoundingBox")
                              if (intersects(dynamic_cast<BoundingVolume<BoundingBox>*>(other->children[i])))
                                    return true;*/
                           //if (dynamic_cast<BoundingVolume<decltype(std::get<1>(other->children[i]->types))>*>(other->children[i])) {
                                /*BoundingVolumeBase* bv = other->children[i];
                                if (intersects(dynamic_cast<BoundingVolume<decltype(*std::get<bv->getTypeAsConst()>(typelist))>*>(other->children[i])))
                                    return true;*/
                           //}
     
                           S<BoundingVolumeBase, 0, true>::get(getType(), *other.children[i]);
                           intersects(dynamic_cast<BoundingVolume<decltype(*S<BoundingVolumeBase, 0, true>::actualType)>&>(*other.children[i]));
                      }
                } /*else {
                    for (unsigned int i = 0; i < children.size(); i++) {
                        if (other->children.size() == 0) {
                            if (children[i]->getType() == "BoundingBox")
                                if (static_cast<BoundingVolume<BoundingBox>*>(children[i])->intersects(static_cast<BoundingVolume<C>*>(other)))
                                    return true;
     
                        } else {
                            for (unsigned j = 0; j < other->children.size(); j++) {
                                if (children[i]->getType() == "BoundingBox" && other->children[i]->getType() == "BoundingBox")
                                    if (static_cast<BoundingVolume<BoundingBox>*>(children[i])->intersects(static_cast<BoundingVolume<BoundingBox>*>(other->children[j])))
                                        return true;
                            }
                        }
                    }
                }*/
            //}
            return false;
        }
        virtual BoundingVolume<D>* clone() {
        }
        virtual bool intersects (BoundingBox &other) {
            return false;
        }
        virtual Vec3f getPosition() {
            return Vec3f(0, 0, 0);
        }
        virtual Vec3f getSize() {
            return Vec3f(0, 0, 0);
        }
        virtual Vec3f getCenter() {
            return Vec3f(0, 0, 0);
        }
        virtual void move (Vec3f t) {
        }
        std::vector<BoundingVolumeBase*> getChildren() {
            return children;
        }
        virtual int getType() = 0;
        virtual ~BoundingVolume() {}
    public :
        std::vector<BoundingVolumeBase*> children;
    };
    }
    #endif // BOUNDING_AREAS

    Car pour le moment ce code n'est juste que dans une librairie.

  12. #12
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    À mon avis ça ne fonctionne pas en l’état :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    actualType = std::get<i>(T::typelist);
    Dans mon code, actualType est un type, pas une variable. Donc l’idée, ce serait plutôt de modifier result.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     public :
        static typename std::tuple_element<i,decltype(T::typelist)>::type actualType;
    Pour la même raison, plutôt utiliser un typedef.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::tuple_cat(typelist, tp);
    ne sert à rien dans ton code. Ça renvoie un nouveau tuple, dont tu ne fais rien. En aucun cas ça ne va modifier ton tuple « typelist ».

    Du coup, certes, ça compile, mais à mon avis ça ne fait pas ce que tu voudrais .

  13. #13
    Invité
    Invité(e)
    Par défaut
    À mon avis ça ne fonctionne pas en l’état :

    actualType = std::get<i>(T::typelist);

    Dans mon code, actualType est un type, pas une variable. Donc l’idée, ce serait plutôt de modifier result.




    public :
    static typename std::tuple_element<i,decltype(T::typelist)>::type actualType;

    Pour la même raison, plutôt utiliser un typedef.
    Bah en réalité je m'en tape de result, je veux juste récupérer le type et bon à la compilation il me dit bien que c'est BoundingVolume<BoundingBox>* le type dans le template ici :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    intersects(static_cast<BoundingVolume<decltype(*S<BoundingVolumeBase, 0, true>::actualType)>&>(*other.children[i]));

    Je ne comprend pas très bien ce que tu veux dire par là.

    Par contre si je fais un dynamic_cast ça ne compile pas.


    std::tuple_cat(typelist, tp);

    ne sert à rien dans ton code. Ça renvoie un nouveau tuple, dont tu ne fais rien. En aucun cas ça ne va modifier ton tuple « typelist ».

    Du coup, certes, ça compile, mais à mon avis ça ne fait pas ce que tu voudrais .
    Hum en effet je voudrais en fait mofidier la typelist mais je sais pas si il y a moyen de le faire sans connaitre les types des classes dérivée à l'avance. (Je ne pense pas u'il y ai moyen)

    Genre faire un truc comme ça :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    static std::tuple<DummyType*, template <typename...> class T> typelist;

    Et ajouter au fur et à mesure les types dans le tuple à l'aide de tuple_cat...

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    template <typename D> BoundingVolumeBase(D* type) {
            if (!odfaeg::details::exists_type<D*, decltype(typelist)>::value) {
                std::tuple<D*> tp = std::make_tuple(type);
                typelist = std::tuple_cat(typelist, tp);
                typeId = nbIds;
                nbIds++;
            } else {
                for (unsigned int i = 0; i < std::tuple_size<decltype(typelist)>::value; i++) {
                    S<BoundingVolumeBase, 0, true>::get(i,*this);
                    if (std::is_same<D*, decltype(S<BoundingVolumeBase, 0, true>::actualType)>::value)
                        typeId = i;
                }
            }
        }

    Il y a moyen de faire ça en c++ ou pas ?

  14. #14
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par Lolilolight Voir le message
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    static std::tuple<DummyType*, template <typename...> class T> typelist;

    Et ajouter au fur et à mesure les types dans le tuple à l'aide de tuple_cat...

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    template <typename D> BoundingVolumeBase(D* type) {
            if (!odfaeg::details::exists_type<D*, decltype(typelist)>::value) {
                std::tuple<D*> tp = std::make_tuple(type);
                typelist = std::tuple_cat(typelist, tp);
                typeId = nbIds;
                nbIds++;
            } else {
                for (unsigned int i = 0; i < std::tuple_size<decltype(typelist)>::value; i++) {
                    S<BoundingVolumeBase, 0, true>::get(i,*this);
                    if (std::is_same<D*, decltype(S<BoundingVolumeBase, 0, true>::actualType)>::value)
                        typeId = i;
                }
            }
        }

    Il y a moyen de faire ça en c++ ou pas ?
    Non, ça ne marchera pas. Tu as besoin d’avoir l’ensemble des classes dérivées lors de la compilation de la classe de base, pour connaître le type réel de typelist. Pour l’instant, je n’ai pas trouvé d’autre solution que de la coder en dur ici.

    Si ta hiérarchie est fixe / évolue peu, ce n’est pas un problème. Si tu souhaites fournir à tes clients la possibilité de rajouter des classes dans la hiérarchie, c’est mort.

  15. #15
    Invité
    Invité(e)
    Par défaut
    Ok c'est mort pour ce que je veux faire alors.

    Bah au moins comme ça je suis fixé.

  16. #16
    Invité
    Invité(e)
    Par défaut Ajout d'elements dans un tuple. (A la compilation)
    Je me demande finalement si ce n'est quand même pas possible. (En définissant de nouveau "tuple_element" pour le tuple.)

    Genre comme ça :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    template <typename T, typename A>
    struct add_element {
        static void add (A element) {
            constexpr int index = std::tuple_size<T>::value;
            static typename std::tuple_element<index, T>::type newtype = element;
        }
    };

    Code cpp : 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
     
    class BoundingVolumeBase {
        public :
        template <typename D> BoundingVolumeBase(D* type) {
            if (!odfaeg::details::exists_type<D*, decltype(typelist)>::value) {
                std::tuple<D*> tp = std::make_tuple(type);
                add_element<decltype(typelist), D*>(type);
                typeId = nbIds;
                nbIds++;
            } else {
                for (unsigned int i = 0; i < std::tuple_size<decltype(typelist)>::value; i++) {
                    S<BoundingVolumeBase, 0, true>::get(i,*this);
                    if (std::is_same<D*, decltype(S<BoundingVolumeBase, 0, true>::actualType)>::value)
                        typeId = i;
                }
            }
        }
        int getType() {
            return typeId;
        }
        static std::tuple<DummyType*> typelist;
        int typeId;
        static int nbIds;
    };

    Ca compile en tout cas mais je suis pas sûr que ça marche, j'ai pas encore testé.

Discussions similaires

  1. Convertir un int en une valeur d'enum
    Par cyrille37 dans le forum Langage
    Réponses: 7
    Dernier message: 07/11/2007, 10h51
  2. Convertir un (int) en (uint)
    Par Remi163 dans le forum MFC
    Réponses: 4
    Dernier message: 28/04/2006, 18h53
  3. comment mettre des int dans une char??
    Par gronaze dans le forum C
    Réponses: 5
    Dernier message: 21/04/2006, 17h02
  4. [FPDF] convertir le contenu d'une popup en pdf
    Par kagura dans le forum Bibliothèques et frameworks
    Réponses: 13
    Dernier message: 23/01/2006, 09h29
  5. Convertir un Int en Hexadécimal
    Par Benjy dans le forum C++Builder
    Réponses: 14
    Dernier message: 12/10/2005, 17h22

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