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++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  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 Expert
    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
    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

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    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

  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

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    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>();
    ...
        }
    }

  6. #6
    Membre Expert
    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
    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.

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