Partage
  • Partager sur Facebook
  • Partager sur Twitter

dans une zone de mémoire en lecture seule

C++ constexpr

    3 février 2019 à 18:12:43

    Bonjour OC,

    à la page 99 de son livre "Effective Modern C++", après le deuxième bloc de code, Mr Scott Meyers, dit :

    constexpr Point midpoint(const Point& p1, const Point& p2) noexcept
    {return { (p1.xValue() + p2.xValue())/2, (p1.yValue()+p1.yValue())/2);
    }
    
    constexpr auto mid = midpoint(p1,p2);

    "même si l'initialisation de l'obet mid implique des appels à des constructeurs, des accesseurs et une fonction non membre, il peut être créé dans une zone de mémoire en lecture seule !"

    J'ai besoin de comprendre la partie que j'ai mis en caractères gras car je ne saisis pas pourquoi il dit cela, alors que jusque maintenant , dans ce conseil , n'est pas question de zone de mémoire en lecture seule.

    Pouvez-vous m'expliquer ?

    Je vous remercie par avance

    CREDIT : "Programmez efficacement en C++, de Scott Meyers (Dunod). Copyright 2016 Dunod pour la version française 978-2-10-074391-9, et 2015 Scott Meyers pour la versio d'origine 978-1-491-90399-5"

    • Partager sur Facebook
    • Partager sur Twitter
      3 février 2019 à 19:18:38

      Quelle est la question exactement :

      • c'est quoi une zone de mémoire en lecture seule ?
      • pourquoi l'objet peut y être créé ?

      Pour le premier point, il faut se rappeler que, sur une grande partie des plateformes, un programme qui s'exécute utilise plusieurs "zones" mémoires, avec des droits d'accès qui peuvent être différents.

      Par exemple la zone où se trouve le code (les instructions) est lisible et exécutable, mais pas modifiable. On peut y trouver aussi les constantes.

      La pile d'exécution, et la zone qui servent pour le tas, sont lisibles et exécutables modifiables , mais ne devraient pas être exécutables.

      Pour le second point, si p1 et p2 ont des valeurs connues à la compilation -je suppose que c'est dans le texte plus haut-, il est possible de calculer aussi midpoint(p1, p2) et puisque le résultat est une constexpr (une constante) on peut le stocker dans une partie non modifiable de la mémoire. No problemo.

      Faudrait voir les conséquences qu'il en tire, dans les phrases suivantes.

      Le point qu'il me semble illustrer, c'est que ce qui est constexpr peut être calculable au moment de la compilation (ce qu'on appelle de l'évaluation partielle), et que si c'est fait, la valeur qui en résulte peut être  présente dans une constante au moment de l'exécution. Une "compile-time constant".

      -
      Edité par michelbillaud 3 février 2019 à 19:48:42

      • Partager sur Facebook
      • Partager sur Twitter
        3 février 2019 à 19:31:47

        Bonsoir MichelBillaud,

        oui, votre interprétation quand vous dîtes :

        "puisque le résultat est une constexpr (une constante) on peut le stocker dans une partie non modifiable de la mémoire. No problemo."

        me semble correspondre à ce que j'attends. Pourquoi est-elle non modifiable s'il vous plaît ?

        Quand vous avez dit :

        La pile d'exécution, et la zone qui servent pour le tas, sont lisibles et exécutables, mais ne devraient pas être exécutables.

        vouliez-vous dire :

        La pile d'exécution, et la zone qui servent pour le tas, sont lisibles et exécutables, mais ne devraient pas être modifiables

        Merci à vous

        -
        Edité par pseudo-simple 3 février 2019 à 19:32:18

        • Partager sur Facebook
        • Partager sur Twitter
          3 février 2019 à 19:45:55

          constexpr auto mid = ...., déclarée constexpr, c'est une constante, donc pas modifiable.

          Oui je me suis embrouillé. Je corrige.

          -
          Edité par michelbillaud 3 février 2019 à 19:48:20

          • Partager sur Facebook
          • Partager sur Twitter
            3 février 2019 à 20:51:21

            Pouvez-vous expliquer votre phrase suivante , car je ne suis pas certain de comprendre (avec un exemple) ? 

            La pile d'exécution, et la zone qui servent pour le tas, sont lisibles et exécutablesmodifiables , mais ne devraient pas être exécutables.

            • Partager sur Facebook
            • Partager sur Twitter
              3 février 2019 à 22:07:09

              Qu'on ne devrait pas pouvoir faire ce genre de choses

              char duCode[] = { ....... }; // une séquence d'octets contenant des instructions
              
              typedef void (*fonction)();
              
              ....
              
              fonction f = (fonction) duCode;
              
              f();             // fait exécuter le code qui est dans le tableau
              

              (déclenche un warning, mais on peut contourner)

              Ca veut dire qu'au niveau matériel, il y a une protection mémoire qui déclenche une interruption si on tente de faire exécuter quelque chose dans une page pour laquelle on a le droit de lecture mais pas d'exécution Il faut aussi que le systeme d'exploitation le gère, en positionnant les droits corrects sur les segments.

              -
              Edité par michelbillaud 3 février 2019 à 22:10:13

              • Partager sur Facebook
              • Partager sur Twitter
                3 février 2019 à 22:48:39

                Je comprends, j'avoue que je ne suis moi-même point accoutumé à voir des instructions dans un tableau de caractères, et qui plus est, à exécuter.

                -
                Edité par pseudo-simple 4 février 2019 à 12:09:20

                • Partager sur Facebook
                • Partager sur Twitter
                  4 février 2019 à 7:11:44

                  C'est la base de la "compilation just in time", par exemple.

                  Le bytecode est lu et traduit sous forme d'instructions natives placées dans un tableau, et zou, exécution du tableau.

                  Et aussi une façon courante d'exploiter les buffer overflows, pour des motivations en général crapuleuses.

                  -
                  Edité par michelbillaud 4 février 2019 à 7:17:39

                  • Partager sur Facebook
                  • Partager sur Twitter
                    4 février 2019 à 13:11:17

                    Salut,

                    Il faut te rappeler qu'un ordinateur, ca ne fonctionne qu'avec des succession de "micro interrupteurs" qui laissent (ou non) passer le courant.

                    Voici une explication simple, et malgré tout correcte, de ce que l'on appelle les bits.

                    Comme un seul interrupteur, c'est fort peu, les bits sont regroupés entre eux, pour former des bytes (en francais, on a tendance à parler d'octet, mais je n'aime pas du tout ce terme: je préfères "multiplet", tant qu'à faire ;) ).

                    Il n'y a rien, dans l'ordinateur, qui permette au processeur de faire la différence entre un byte (ou peut-être plusieurs) qui représente(nt) une instruction qu'il est capable d'exécuter et une donnée qu'il devrait utiliser, si ce n'est ... la position du byte concerné dans l'application.

                    Le processeur dispose, entre autres, d'un "endroit particulier" (appelé pointeur d'instruction) où il stocke systématiquement l'adresse à laquelle se trouve le(s) byte(s) qu'il considérera être une instruction.

                    Pour être tout à fait complet, il s'agit en réalité "tout simplement" d'un registre qui est spécialement dédié à cet usage, mais bon... Cela n'a que peu d'intérêt ici.

                    Comme il connaît le nombre de données dont toutes les instructions ont besoin pour travailler, il sait que les X bytes qui sui(ven)t l'instruction représenteront la première donnée dont l'instruction a besoin pour travailler, (si tant est qu'elle ait besoin d'au moins une donnée), que les Y bytes qui viendront juste après les X premier représenteront la deuxième donnée dont l'instruction a besoin, et, le cas échéant, que les Z bytes qui vien(nen)t après les Y deuxième représentent la troisième donnée dont l'instruction a besoin (je crois qu'il n'y a pas d'instruction qui ait besoin de plus de trois données, mais, si je me trompe sur ce coup là, on peut allonger la liste :D )

                    Si bien que, quand le processeur commence à exécuter une instruction donnée, il met automatiquement le pointeur sur instruction à jour pour qu'il pointe sur ... l'instruction qu'il devra exécuter "juste après".

                    Suite à cette explication, on se rend bien compte que la seule chose qui permette au processeur de considérer "un ensemble de bytes" (quelle que soit sa taille) comme étant une donnée, c'est parce qu'il y accède -- d'une manière ou d'une autre -- (le plus souvent au travers de l'adresse mémoire à laquelle il se trouve) afin "d'alimenter" l'instruction qu'il doit effectuer en donnée.

                    Depuis quarante ans que les ordinateurs existent, les fondeurs de processeurs se sont rendus compte que laisser le processeur considérer n'importe quel byte (ou ensemble de bytes) comme étant une instruction, ce n'était pas vraiment "la bonne idée du siècle".

                    Tout comme ils (les fondeurs de processeurs) se sont rendus compte que ... certaines données ne peuvent surtout pas être modifiées.  Imagines un peu la catastrophe si on venait à décider (en cours d'exécution) que la donnée qui représente PI (3.1415926...) se mettait d'un seul coup à valoir 6.2831852... on serait pas dans la merde, hein?

                    Ils se sont donc arrangés pour définir différents endroits (appelés segments, pour la plupart) dans lesquels les différents bytes ne peuvent être utilisés que ... de manière particulière.

                    Parmi ceux-ci on trouve un segment dans lequel les données ne peuvent pas être modifiées (idéal pour maintenir la valeur de pi, par exemple), un autre qui fournit la suite des instructions qui doivent être exécutée, un troisième qui représentera la pile d'appels des fonctions, et bien d'autres encore.

                    Mais ce qui importe, c'est surtout que chaque segment subit ses propres restrictions et autorise (ou non ) un certain nombre d'actions qui lui sont spécifiques

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                      5 février 2019 à 0:05:19

                      Merci. Je reviens maintenant au constexpr lui-même qui est l'objet de ce fil de discussion, maintenant que j'ai terminé de lire le chapitre. J'ai plusieurs questions :

                      1) Première question (je précise pour Joe_link_noir que ma question a du sens, il suffit de se reporter à la définition d'une fonction constexpr) :

                      Pouvez-vous m'indiquer un exemple dune fonction non constexpr, qui ne l'est pas pour le motif suivant : cette fonction non constexpr est appelée avec des constantes connues à la compilation. Cependant elle n'est pas capable de produire une constante connue à la compilation.

                      2) Deuxième question :

                      Monsieur Scott Meyers dit deux choses qui me paraissent contradictoires (d'où le besoin d'explications complémentaires) : 

                      il dit :

                      Les fonctions constexpr peuvent être employées dans les contextes qui demandent des constantes connues à la compilation. Si les valeurs des arguments transmis à une fonction constexpr employée dans un tel contexte sont connues à la compilation, le résultat sera déterminée pendant la compilation. Si l'une des valeurs des arguments n'est pas connue à la compilation, le code sera rejeté.

                      Or juste après, il dit :

                      Lorsqu'une fonction constexpr est appelée avec une ou plusieurs valeurs inconnues au moment de la compilation, elle se comporte comme une fonction normale, en déterminant son résultat au cours de l'exécution. Nous n'avons donc pas besoin de deux fonctions... La seule fonction constexpr suffit.

                      Les deux assertions que j'ai mises en caractère gras, me donnent l'impression d'être "contradictoires". 

                      Pourriez-vous m'expliquer pourquoi ce n'est pas contradictoire ?

                      Merci par avance

                      -
                      Edité par pseudo-simple 5 février 2019 à 0:37:03

                      • Partager sur Facebook
                      • Partager sur Twitter
                        5 février 2019 à 0:20:26

                        > 1) Pouvez-vous m'indiquer un exemple de fonction non constexpr car appelée avec des arguments connnus à la compilation, mais qui n'est pas capable de produire une constante connue à la compilation ?

                        Cette question n'a aucun sens.

                        > Les fonctions constexpr peuvent être employées dans les contextes qui demandent des constantes connues à la compilation.

                        C’est-à-dire stocker la valeur dans une variable constexpr. En dehors de ce contexte, une fonction constexpr se comporte comme n'importe quelle fonction.

                        -
                        Edité par jo_link_noir 5 février 2019 à 0:20:40

                        • Partager sur Facebook
                        • Partager sur Twitter
                          5 février 2019 à 7:05:50

                          Le point qu'il a loupé, c'est "dans des contextes qui demandent des constantes connues à la compilation".

                          C'est très probablement l'effet d'une mauvaise traduction "to demand", en anglais, c'est _exiger_, pas demander.

                          C'est à dire à un endroit où on est en train de définir une constante

                          constexpr int  XYZ = f(.....);
                          

                          et pour ça on exige d'avoir la valeur  f(....) au moment de la compilation. Il faut pouvoir l'évaluer.

                          alors dans que

                          int toto = f(.....);
                          

                          l'évaluation effective peut attendre le moment de l'exécution, même si les arguments de f sont connus, constants et suffisants pour déterminer la valeur.

                          Le problème avec les bouquins informatiques en français, c'est qu'ils sont souvent traduits avec les pieds, et donc il faut quand même connaitre l'anglais pour voir d'où vient une phrase incompréhensible ou juste bizarre. Et imaginer quel était le texte en anglais, et connaitre les erreurs de traduction habituelles. Autant lire directement en anglais.

                          -- c'est comme quand vous voulez acheter des trucs électroniques chez les chinois. On vous vous propose des "conseils de développement" (board = carte ou conseil). Une fois qu'on le sait...

                           Y avait un truc marrant aussi avec ship, navire et aussi verbe envoyer. Faudra que je retrouve. "manutention du navire" = frais de port.

                          -
                          Edité par michelbillaud 5 février 2019 à 8:31:37

                          • Partager sur Facebook
                          • Partager sur Twitter
                            5 février 2019 à 9:33:58

                            Bonjour MichelBillaud,

                            pourriez-vous me donner un exemple pour ma première question ? c'est-à-dire un exemple de fonction qui n'a pas le droit d'être déclarée constexpr ? (à part les cas d'exemples renvoyant un void en C++11 ou une fonction modifiant l'élément sur lequel elle s'applique en C++11) 

                            Et pour ma deuxième question, je n'ai pas saisi votre explication.

                            Par avance merci pour votre aide.

                            • Partager sur Facebook
                            • Partager sur Twitter
                              5 février 2019 à 9:53:31

                              YES, man a écrit:

                              Bonjour MichelBillaud,

                              pourriez-vous me donner un exemple pour ma première question ? c'est-à-dire un exemple de fonction qui n'a pas le droit d'être déclarée constexpr ? (à part les cas d'exemples renvoyant un void en C++11 ou une fonction modifiant l'élément sur lequel elle s'applique en C++11) 

                              Et pour ma deuxième question, je n'ai pas saisi votre explication.

                              Par avance merci pour votre aide.

                              int variable;
                              int foo(int n)           {  return n * variable; }
                              constexpr int bar(int n) {  return n * variable; }
                              


                              erreur dans la seconde fonction : f.cc:3:49: error: the value of ‘variable’ is not usable in a constant expression

                              --- second point :

                              le contexte exige que la fonction f soit capable de fournir une valeur calculable pendant la compilation, parce qu'on a besoin de cette valeur pour initialiser une constante connue dès la compilation.

                              -
                              Edité par michelbillaud 5 février 2019 à 9:56:21

                              • Partager sur Facebook
                              • Partager sur Twitter
                                5 février 2019 à 11:29:18

                                Alors pourquoi est-il dit :

                                Lorsqu'une fonction constexpr est appelée avec une ou plusieurs valeurs inconnues au moment de la compilation, elle se comporte comme une fonction normale, en déterminant son résultat au cours de l'exécution.

                                alors que l'exemple que vous avez donné montre que le code est rejeté pour une variable qui n'est pas clairement déterminée au moment de la compilation ?

                                Comment concilier les deux idées puisque en l'occurence ne passe même pas la compilation ? comment pourrait-il déterminer son résultat au cours de l'exécution ?

                                Je vous remercie.

                                -
                                Edité par pseudo-simple 5 février 2019 à 12:13:20

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  5 février 2019 à 11:40:13

                                  Comme indiquer par @michelbillaud, regardez ces mêmes passages dans la version originale, en anglais.

                                  Il y a des chances qu'ils soient bien plus clairs et exacts dans la langue de Trump.

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                    5 février 2019 à 12:13:04

                                    J'ai la version anglaise, et c'est la même compréhension.

                                    Merci par avance pour votre aide

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      5 février 2019 à 12:35:09

                                      YES, man a écrit:

                                      Alors pourquoi est-il dit :

                                      Lorsqu'une fonction constexpr est appelée avec une ou plusieurs valeurs inconnues au moment de la compilation, elle se comporte comme une fonction normale, en déterminant son résultat au cours de l'exécution.

                                      constexpr int carre(n) { return n*n; }
                                      
                                      ...
                                      
                                      int n;
                                      std::cin >> n;
                                      std::cout << carre(n);
                                      



                                      • la fonction carre est "constexpr"
                                      • elle est appelée avec une valeur inconnue à la compilation
                                      • elle se comporte comme une fonction normale (*)
                                      • son résultat sera déterminé au cours de l'execution

                                      et voila

                                      (*) Pour autant que quelque chose puisse être normal en C++.

                                      -
                                      Edité par michelbillaud 5 février 2019 à 12:36:03

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        5 février 2019 à 14:30:28

                                        Par exemple :

                                        constexpr int carre(int n) { return n * n; }
                                        
                                          const int m = 3;
                                          std::array<double,carre(m)>  tableau1; // on obtient un tableau de 9 double
                                        
                                          int n = 2;
                                          std::array<double,carre(n)>  tableau2; // erreur carre(n) n'est pas une constante de compilation!

                                        Dans le second cas, la fonction reçoit un paramètre qui n'est pas une constante de compilation, c'est un résultat d’exécution même si ici le compilateur 'sait' bien que le résultat carre(n) vaut 4, il sait l'optimiser mais il devra refuser la compilation.

                                        • Partager sur Facebook
                                        • Partager sur Twitter

                                        En recherche d'emploi.

                                          5 février 2019 à 18:08:18

                                          En fat, si on reprend l'exemple de Daflab:

                                          int n = 2; // n n'EST PAS CONSIDERE comme une constante 
                                                     // comme CONSTANTE de compilation (1)
                                            std::array<double,carre(n)>  tableau2; //carre(n) NE PEUT DONC PAS
                                                                                   // être considérée comme 
                                                                                   // constante (2)

                                          (1) : n est, certes, une valeur connue à la compilation, mais, comme elle ne subit aucune restriction de constance (n n'est pas déclaré comme const, et encore moins comme constexpr) la valeur de n peut tout à fait être modifiée par programmation au sein de "n'importe quelle fonction" successible de la connaître.

                                          Le compilateur ne peut donc pas fournir la moindre garantie que n vaudra ... toujours 2; et, bien sur, cela implique qu'il ne peut pas la considèrer pas comme étant constante.

                                          (2)Vu que n ne peut absolument pas être considérée comme étant constante par le compilateur, nous nous trouvons face une situation dans laquelle l'appel carre(n) ne peut en aucun cas être considérée comme une constexpr (encore une fois: une fonction quelconque risque de modifier la valeur de n avant que l'on ne fasse appel à carre).

                                          si bien que le résultat lors de l'appel à carre(n) n'offre aucune garantie d'être égal à 4 :  pour autant qu'on sache, ce sera égal à la multiplication de la valeur de n par elle-même au moment de l'appel à la fonction. Et, pour évaluer la valeur de n, il faut prendre en compte toutes les fonctions (susceptibles d'accéder à n) par lesquelles nous serons  passés ... en cours d'exécution.

                                          Malgré le fait que carre(int) soit déclaré comme "fournissant une expression constante" comme résultat, le simple fait que le paramètre qui lui est donné dans le cas bien précis de carre(n) est donc tout ... sauf constant.

                                          Et, à partir de là, il n'y a plus rien à faire : on ne peut pas utiliser le résultat obtenu par cet appel pour "compléter" une expression qui doit être constante (et qui plus est une constante de compilation), comme le nombre d'éléments qu'un std::array est en mesure de contenir.

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                          Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                                            5 février 2019 à 22:18:06

                                            Merci beaucoup, c'est très clair maintenant avec les différents postes que vous avez tous envoyés.

                                            J'arrive à la conclusion de la partie sur constexpr. Il y a à la fin une idée que j'ai besoin de comprendre avec un exemple car aucun exemple n'est donné. Voici ce qui est dit :

                                            "Si nous déclarons un objet ou une fonction constexpr, le code client peut l'employer dans de tels contextes. Si nous décidons ensuite que la déclaration constexpr était une erreur et que nous la supprimons, il est possible que de grandes quantités de code client ne compilent plus. (Le simple ajout d'entrées/sorties  à une fonction pour le débogage ou le réglage des performances peut conduire à un tel problème.) .... 

                                            Pouriez-vous me proposer un exemple simple avec un code pour ce que l'auteur a voulu dire pour ce que j'ai mis en caractères gras sur l'ajout d'entrées/sorties ?

                                            Je vous remercie encore par avance.

                                            -
                                            Edité par pseudo-simple 5 février 2019 à 22:30:06

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              5 février 2019 à 22:51:09

                                              Sais-tu ce que sont les entrées/sorties ?

                                              -
                                              Edité par jo_link_noir 5 février 2019 à 22:51:42

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                              Anonyme
                                                6 février 2019 à 2:50:22

                                                Bonjour,

                                                quelqu'un peut-il m'aider avec un exemple concret par rapport à ce passage du livre que j'ai cité ?

                                                Par avance merci

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  6 février 2019 à 3:49:15

                                                  Tu demandes trop souvent des exemples. Normalement, si tu comprends les problématiques, tu devrais etre capable d'écrire toi même ces exemples et faire tes propres tests. Arrêtez de demander aux autres de faire ton boulot d'écriture de code, cela fait partie de l'apprentissage.
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    6 février 2019 à 9:08:00 - Message modéré pour le motif suivant : Message complètement hors sujet


                                                      6 février 2019 à 10:51:08 - Message modéré pour le motif suivant : Message complètement hors sujet


                                                        6 février 2019 à 10:54:00

                                                        > Google : "C++ entrées sorties" (si tu ne sais pas ce que c'est mais comme tu n'as pas répondu à la question de jo_link_noir...)

                                                        > Tu essaies

                                                        > Tu constates

                                                        A quel moment on doit t'aider dans ce processus ?

                                                        EDIT : Au passage, c'est une démarche des plus scientifiques ! :)

                                                        -
                                                        Edité par Maluna34 6 février 2019 à 11:08:14

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          6 février 2019 à 15:04:24

                                                          Je prend bien note que tu me donnes pas l'autorisation de te tutoyer.

                                                          YES, man a écrit:

                                                          "Si nous déclarons un objet ou une fonction constexpr, le code client peut l'employer dans de tels contextes. Si nous décidons ensuite que la déclaration constexpr était une erreur et que nous la supprimons, il est possible que de grandes quantités de code client ne compilent plus. (Le simple ajout d'entrées/sorties  à une fonction pour le débogage ou le réglage des performances peut conduire à un tel problème.) .... 

                                                          La phrase dont tu demandes un code d'exemple est placée dans un contexte : "un objet ou une fonction constexpr", "on supprime le constexpr, etc.

                                                          Si tu as compris la problématique, tu dois être capable d'écrire le code de ce contexte (ie un objet ou une fonction avec et sans constexpr). Et tu devrais être capable d'écrire du code client (ie du code qui utilise cette fonction ou cet objet) et qui ne compile plus si on retire le constexpr. 

                                                          Ne pas comprendre un point de l'explication, c'est une chose. Mais si tu ne comprends pas le contexte, cela ne sert a rien qu'on te donne le code. C'est a toi de faire tes tests, d'écrire le code du contexte et rechercher des codes clients qui ne compilent plus si on retire constexpr.

                                                          Le minimum du respect, c'est de montrer que tu bosses et que tu n'attends pas de nous qu'on écrive tous tes codes.

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter

                                                          dans une zone de mémoire en lecture seule

                                                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                          • Editeur
                                                          • Markdown