{"id":595,"date":"2023-04-27T10:34:10","date_gmt":"2023-04-27T08:34:10","guid":{"rendered":"https:\/\/naupacte.com\/?p=595"},"modified":"2023-04-27T10:39:38","modified_gmt":"2023-04-27T08:39:38","slug":"les-operateurs-associatifs-du-c-sont-asociaux","status":"publish","type":"post","link":"https:\/\/naupacte.com\/index.php\/2023\/04\/27\/les-operateurs-associatifs-du-c-sont-asociaux\/","title":{"rendered":"Les op\u00e9rateurs associatifs du C++ sont asociaux"},"content":{"rendered":"\n<p>Le C++ a le d\u00e9faut d&#8217;\u00eatre un peu binaire&#8230; dans sa fa\u00e7on de traiter les op\u00e9rations <em>n<\/em>-aires qui se moque bien de l&#8217;intention associative du programmeur. Faut-il attendre un compilateur quantique avec \u00e9tats non-binaires pour traiter ensemble les op\u00e9randes associ\u00e9es par les parenth\u00e8ses? \ud83d\ude09<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Le probl\u00e8me<\/h2>\n\n\n\n<p>Bien que les op\u00e9rateurs + et * soient associatifs du point de vue math\u00e9matique, le C++ traite leurs op\u00e9randes 2 par 2 de gauche \u00e0 droite. Ainsi <code class=\"\" data-line=\"\">a+b+c+d<\/code> est vu comme: <code class=\"\" data-line=\"\">((a+b)+c)+d<\/code>.<\/p>\n\n\n\n<p>sans qu\u2019il y ait moyen de sp\u00e9cifier que l\u2019on veut une somme de quatre op\u00e9randes autrement que par l\u2019appel, moins expressif, d\u2019une fonction comme <code class=\"\" data-line=\"\">sum(a,b,c,d)<\/code>, Certes, par le moyen classique des <em>expression-templates<\/em>, on pourrait aboutir au r\u00e9sultat voulu, mais au prix de perdre le respect des parenth\u00e8ses. Par exemple, dans le cas o\u00f9 le programmeur \u00e9crirait <code class=\"\" data-line=\"\">(a+b+c)+d<\/code>, une <em>expression-template<\/em> pourrait grouper les trois premiers termes, mais finirait par y agr\u00e9ger le quatri\u00e8me. <strong>A moins d&#8217;ajouter au standard C++ un op\u00e9rateur d\u2019appel externe (<em>static operator<\/em> ())<\/strong>, qui op\u00e9rerait sur le r\u00e9sultat de <code class=\"\" data-line=\"\">a+b+c<\/code>, il n\u2019y a aucun moyen de garder trace des parenth\u00e8ses.<\/p>\n\n\n\n<p><strong>Ceci est un probl\u00e8me s\u00e9rieux pour une interface de programmation, car il est important de respecter l\u2019intention exprim\u00e9e par l\u2019utilisateur.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Proposition pour le C++<\/h2>\n\n\n\n<p>Soit un type <code class=\"\" data-line=\"\">Expr<\/code> sur lequel nous proposons la possibilit\u00e9 de d\u00e9finir l\u2019op\u00e9rateur <code class=\"\" data-line=\"\">+<\/code> suivant:<\/p>\n\n\n\n<pre class=\"wp-block-code language-cpp\"><code class=\"\" data-line=\"\">enum ExprOperator { ..., OpSum, ... OpProduct, ...};\nstruct Expr { ExprOperator; std::vector&lt;Expr&gt; operands;};\nstd::vector&lt;Expr&gt; to_vector(Expr... ee);\n\nExpr operator+(Expr e, Expr... ee) \/\/ &lt;- proposition\n{\n    return Expr { OpSum, to_vector(e,ee...) };\n}<\/code><\/pre>\n\n\n\n<p>A noter: ce programme compile, mais l&#8217;op\u00e9rateur+ n&#8217;est compris qu&#8217;avec deux arguments, ce qui est un peu limit\u00e9 pour un deuxi\u00e8me argument variadique. Nous voulons qu&#8217;il soit accept\u00e9 pour ce qu&#8217;il est. Avec ceci, nous sommes capables de traduire <code class=\"\" data-line=\"\">(a+b+c)+d<\/code> en <code class=\"\" data-line=\"\">Expr{OpSum,{Expr{OpSum,{a,b,c}},d<\/code>} respectant l\u2019original.<\/p>\n\n\n\n<p>Bien s\u00fbr, toutes les variantes prenant <code class=\"\" data-line=\"\">const Expr&amp;<\/code> et <code class=\"\" data-line=\"\">Expr&amp;&amp;<\/code> sont possibles.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conversions implicites ou op\u00e9rations avec d\u2019autres types<a href=\"file:\/\/\/Users\/matthieu\/C++prop\/build\/html\/associative_operators.html#conversions-implicites-ou-operations-avec-d-autres-types\"><\/a><\/h2>\n\n\n\n<p>Bien souvent, ayant une variable <code class=\"\" data-line=\"\">a<\/code> de type <code class=\"\" data-line=\"\">Expr<\/code>, nous voulons lui ajouter un type num\u00e9rique, par exemple 1, comme dans <code class=\"\" data-line=\"\">a+1<\/code> ou <code class=\"\" data-line=\"\">1+a<\/code> sans pr\u00e9ciser <code class=\"\" data-line=\"\">a+Expr(1)<\/code> ou <code class=\"\" data-line=\"\">Expr(1)+a<\/code>, ce qui ruinerait l\u2019\u00e9l\u00e9gance de notre expression. L\u2019op\u00e9rateur <code class=\"\" data-line=\"\">+<\/code> binaire permet classiquement de traiter cela. Comment le g\u00e9n\u00e9raliser \u00e0 une somme \u00e0 op\u00e9randes multiples, comme dans <code class=\"\" data-line=\"\">1+a+b<\/code> ou <code class=\"\" data-line=\"\">a+1+b<\/code>?<\/p>\n\n\n\n<p>Nous proposons d\u2019utiliser les concepts en permettant d\u2019\u00e9crire:<\/p>\n\n\n\n<pre class=\"wp-block-code language-cpp\"><code class=\"\" data-line=\"\">Expr operator+(Expr e, auto convertible_to&lt;Expr&gt;... ee)<\/code><\/pre>\n\n\n\n<p>Le probl\u00e8me est que nous n\u2019avons pas toujours un type <code class=\"\" data-line=\"\">Expr<\/code> en premi\u00e8re position, comme dans le cas <code class=\"\" data-line=\"\">1+a+b<\/code>. Nous proposons donc que le C++ interpr\u00e8te cette d\u00e9finition comme: op\u00e9randes multiples dont un de type <code class=\"\" data-line=\"\">Expr<\/code> et les autres de type <code class=\"\" data-line=\"\">convertible_to&lt;Expr&gt;<\/code>.<\/p>\n\n\n\n<p>Une fa\u00e7on peut-\u00eatre plus acceptable pour les compilateurs serait d\u2019\u00e9crire:<\/p>\n\n\n\n<pre class=\"wp-block-code language-cpp\"><code class=\"\" data-line=\"\">Expr operator+(auto convertible_to&lt;Expr&gt;... ee1, Expr e, auto convertible_to&lt;Expr&gt;... ee2)<\/code><\/pre>\n\n\n\n<p>dans lequel <code class=\"\" data-line=\"\">e<\/code> serait la premi\u00e8re parmi les op\u00e9randes qui soit de type <code class=\"\" data-line=\"\">Expr<\/code>.<\/p>\n\n\n\n<p>Cette possibilit\u00e9 serait r\u00e9serv\u00e9e aux op\u00e9rateurs associatifs non bool\u00e9ens (+,*,\u2026). Pour les op\u00e9rateurs bool\u00e9ens, une meilleure proposition est envisag\u00e9e.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Le C++ a le d\u00e9faut d&#8217;\u00eatre un peu binaire&#8230; dans sa fa\u00e7on de traiter les op\u00e9rations n-aires qui se moque bien de l&#8217;intention associative du programmeur. Faut-il attendre un compilateur quantique avec \u00e9tats non-binaires pour traiter ensemble les op\u00e9randes associ\u00e9es par les parenth\u00e8ses? \ud83d\ude09 Le probl\u00e8me Bien que les op\u00e9rateurs + et * soient associatifs du point de vue math\u00e9matique, le C++ traite leurs op\u00e9randes 2 par 2 de gauche \u00e0 droite. Ainsi a+b+c+d est vu comme: ((a+b)+c)+d. sans qu\u2019il y ait moyen de sp\u00e9cifier que l\u2019on veut une somme de quatre op\u00e9randes autrement que par l\u2019appel, moins expressif, d\u2019une fonction comme sum(a,b,c,d), Certes, par le moyen classique des expression-templates, on pourrait aboutir au r\u00e9sultat voulu, mais au prix de perdre le respect des parenth\u00e8ses. Par exemple, dans le cas o\u00f9 le programmeur \u00e9crirait (a+b+c)+d, une expression-template pourrait grouper les trois premiers termes, mais finirait par y agr\u00e9ger le quatri\u00e8me. A moins d&#8217;ajouter au standard C++ un op\u00e9rateur d\u2019appel externe (static operator ()), qui op\u00e9rerait sur le r\u00e9sultat de a+b+c, il n\u2019y a aucun moyen de garder trace des parenth\u00e8ses. Ceci est un probl\u00e8me s\u00e9rieux pour une interface de programmation, car il est important de respecter l\u2019intention exprim\u00e9e par l\u2019utilisateur. Proposition pour le C++ Soit un type Expr sur lequel nous proposons la possibilit\u00e9 de d\u00e9finir l\u2019op\u00e9rateur + suivant: A noter: ce programme compile, mais l&#8217;op\u00e9rateur+ n&#8217;est compris qu&#8217;avec deux arguments, ce qui est un peu limit\u00e9 pour un deuxi\u00e8me argument variadique. Nous voulons qu&#8217;il soit accept\u00e9 pour ce qu&#8217;il est. Avec ceci, nous sommes capables de traduire (a+b+c)+d en Expr{OpSum,{Expr{OpSum,{a,b,c}},d} respectant l\u2019original. Bien s\u00fbr, toutes les variantes prenant const Expr&amp; et Expr&amp;&amp; sont possibles. Conversions implicites ou op\u00e9rations avec d\u2019autres types Bien souvent, ayant une variable a de type Expr, nous voulons lui ajouter un type num\u00e9rique, par exemple 1, comme dans a+1 ou 1+a sans pr\u00e9ciser a+Expr(1) ou Expr(1)+a, ce qui ruinerait l\u2019\u00e9l\u00e9gance de notre expression. L\u2019op\u00e9rateur + binaire permet classiquement de traiter cela. Comment le g\u00e9n\u00e9raliser \u00e0 une somme \u00e0 op\u00e9randes multiples, comme dans 1+a+b ou a+1+b? Nous proposons d\u2019utiliser les concepts en permettant d\u2019\u00e9crire: Le probl\u00e8me est que nous n\u2019avons pas toujours un type Expr en premi\u00e8re position, comme dans le cas 1+a+b. Nous proposons donc que le C++ interpr\u00e8te cette d\u00e9finition comme: op\u00e9randes multiples dont un de type Expr et les autres de type convertible_to&lt;Expr&gt;. Une fa\u00e7on peut-\u00eatre plus acceptable pour les compilateurs serait d\u2019\u00e9crire: dans lequel e serait la premi\u00e8re parmi les op\u00e9randes qui soit de type Expr. Cette possibilit\u00e9 serait r\u00e9serv\u00e9e aux op\u00e9rateurs associatifs non bool\u00e9ens (+,*,\u2026). Pour les op\u00e9rateurs bool\u00e9ens, une meilleure proposition est envisag\u00e9e.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[33],"tags":[37],"class_list":["post-595","post","type-post","status-publish","format-standard","hentry","category-cpp-fr","tag-c-fr"],"_links":{"self":[{"href":"https:\/\/naupacte.com\/index.php\/wp-json\/wp\/v2\/posts\/595","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/naupacte.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/naupacte.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/naupacte.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/naupacte.com\/index.php\/wp-json\/wp\/v2\/comments?post=595"}],"version-history":[{"count":6,"href":"https:\/\/naupacte.com\/index.php\/wp-json\/wp\/v2\/posts\/595\/revisions"}],"predecessor-version":[{"id":677,"href":"https:\/\/naupacte.com\/index.php\/wp-json\/wp\/v2\/posts\/595\/revisions\/677"}],"wp:attachment":[{"href":"https:\/\/naupacte.com\/index.php\/wp-json\/wp\/v2\/media?parent=595"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/naupacte.com\/index.php\/wp-json\/wp\/v2\/categories?post=595"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/naupacte.com\/index.php\/wp-json\/wp\/v2\/tags?post=595"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}