Journal Une structure partiellement constante en C++

Posté par (page perso) . Licence CC by-sa.
Tags :
27
6
juil.
2018

Hop, quelques réflexions sur un langage non réflexif.

Si on veut un tableau de taille statique, on peut utiliser depuis C++11 la classe std::array<T, N>.

std::array<long, 5> my_array{{1, 2, 3, 5, 8}};

Si on veut forcer ce tableau à ne contenir que des constantes utilisables à compile-time, on a la possibilité de marquer cette déclaration constexpr.

constexpr std::array<long, 5> my_array{{1, 2, 3, 5, 8}};

Mais si on veut la marquer partiellement constante ? Et bien je soumets à votre sagacité la déclaration suivante :

std::tuple<long, std::integral_constant<long, 2>, long, std::integral_constant<long, 5>, long> my_array{1, {}, 3, {}, 8};

Alors certes on perd la possibilité d'itérer facilement (mais il reste possible de faire un visiteur de tuple), par contre on gagne en place mémoire (un std::integral_constant<...> ne prend pas de place), et on donne une info au compilateur pour, propager des constantes avec certitude, comme on peut le voir sur cet exemple.

On notera que cette astuce ne marche que grâce à l'opérateur de conversion implicite défini dans le type std::integral_constant. Mais l'astuce est plaisante.

Et n'en déplaise aux cyclistes, dans un monde peuplé d'auto, cette information portée par le type peut se propager assez loin !

  • # Le C++ est terrible... et ce journal l'illustre bien

    Posté par . Évalué à 9.

    Au départ, un problème dont on n'est pas sûr qu'il en soit un, et à l'arrivée, une solution dont on n'est pas sûr qu'elle a un intérêt.

    Oui, je suis peut-être un peu sec et à l'emporte-pièce, mais franchement… ai-je tort?

    • [^] # Re: Le C++ est terrible... et ce journal l'illustre bien

      Posté par . Évalué à 2.

      Au départ, un problème dont on n'est pas sûr qu'il en soit un, et à l'arrivée, une solution dont on n'est pas sûr qu'elle a un intérêt.

      Oui, je suis peut-être un peu sec et à l'emporte-pièce, mais franchement… ai-je tort?

      Je ne vois pas l'interret non plus de melanger des constantes avec des variables.

      Mais utiliser des elements de syntaxe exotique a contresens ne me semble pas etre une faute du langage mais du programmeur.

      En Scala j'ai aussi des moments d'inspiration pour utiliser un element de syntaxe un peu rare. J'essaie mais je reviens toujours a une syntaxe plus commune quand il n'y a pas d'avantage clair. Parfois il y a bien un avantage.

      Mais scala a une des grammaire les plus simple parmi les language a typage statique. Le probleme serait d'avoir un grand nombre d'element de syntaxes peu connues, qui marchent vraiment et qui surprennent regulierement le programmeur.

    • [^] # Re: Le C++ est terrible... et ce journal l'illustre bien

      Posté par . Évalué à 10.

      La question n'est pas de savoir si tu as tort ou pas, mais plus tôt si tu as compris la démarche du journal. Serge nous présente toujours des aspects pointus du c++. Soit parce qu'il les utilise dans sa génération de code (c'est alors du code généré donc les besoins ne sont pas les même) soit juste des choses possibles du langage part amusement ce qui me semble être le cas ici.

      Ce genre de choses permettent de voir des mécanismes des templates, c'est cool.

    • [^] # Re: Le C++ est terrible... et ce journal l'illustre bien

      Posté par (page perso) . Évalué à 10.

      un problème dont on n'est pas sûr qu'il en soit un

      J'ai effectivement assez peu motivé mon cas d'usage. Si tu as une structure de tableau qui a comme variable membre un tableau qui contient à chaque indice le nombre d'éléments dans cette dimension, par exemple :

      template<class T, size_t N>
      class ndarray {
          std::array<long, N> shape;
          T* data;
      };

      Si l'utilisateur sait que la dernière dimension vaut toujours 3, par exemple parce que c'est une matrice de pixels, cette représentation va être pénalisante quand on voudra par courir la dernière dimension, car le compilateur n'a pas moyen d'éviter l'itération. En résultent des temps d'exécution déplorables.

      for(long i = 0, n = a.shape[2]; i < n; ++i)
          a.data[index(i)];
      

      Si on encode dans le type de shape l'information comme quoi la dernière dimension est constante (et petite), et que cette constante est connue, on arrive à

      template<class T, class pS>
      class ndarray {
          pS shape;
          T* data;
      };

      et le compilo aura toutes les informations pour dérouler complètement l'itération.

      une solution dont on n'est pas sûr qu'elle a un intérêt

      J'espère que maintenant qu'elle est motivée, son intérêt transparait mieux :-)

      je suis peut-être un peu sec

      Le demi-sec, c'est moyen, j'ai une nette préférence pour le brut bien râpeu, mais bon, les goûts et les couleurs…

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.