Partage
  • Partager sur Facebook
  • Partager sur Twitter

container.size() ou std::size(container)

Sujet résolu
    10 août 2020 à 14:58:42

    Bonjour, je me demandais s'il valait mieux utiliser 
    container.size()

    ou

    std::size(container)

    J'ai vu sur un sujet que std::size() est assez récent (C++ 17) et que les compilateurs d'avant 2018 ne le supportaient pas.

    (De mon côté, je n'ai aucun problème car j'ai VS2019 à jour).

    Est-ce qu'il y a une différence en termes de rapidité/optimisation/lisibilité/préférence pour des projets pro ?

    Bonne après-midi

    • Partager sur Facebook
    • Partager sur Twitter
      10 août 2020 à 15:56:07

      Salut,

      Non, il n'y a aucune différence à craindre entre container.size() et std::size(container).

      La deuxième (std::size(container) ) participe à  une politique de "rationalisation" et de "modernisation" de la bibliothèque standard lancée par le comité de normalisation.

      En effet, la bibliothèque standard telle qu'on la connai(ssai)t (avant C++17) a été majoritairement développée à une époque où l'idée que la programmation orientée objets représentait la seule solution valable à tous les maux du monde (informatique) était très implantée dans la communauté des développeurs.

      C'est la raison pour laquelle, en dehors de quelques algorithmes très particuliers, une très grosse partie des fonctionnalités offertes par la bibliothèque standard est présentée sous forme de classes, avec leurs  fonctions membres.

      Depuis, on s'est rendu compte que la programmation orientée objets n'était pas ** forcément ** la panacée et même qu'elle avait tendance à complexifier énormément certains mécanismes qui auraient pu s'en passer.

      Mieux encore, on est revenu à  la raison et on a admis le fait qu'une fonction libre

      • permettait l'encapsulation des données aussi  bien que les fonction membres
      • favorisait le respect de l'ISP (Interface Segregation Principle ou principe de ségrégation des interface, le I de SOLID) en permettant d'élargir les services rendus par les classes (et les structures) sans avoir à modifier celles-ci en profondeur.

      En effet, toute fonction libre manipulant une structure ou une classe fait, implicitement, partie de l'interface de cette classe ou de cette structure, exactement au même titre que les fonctions membres que cette classe ou cette structure peut exposer.

      Le comité de normalisation a donc décidé de "libéraliser" plusieurs fonctions membres des principales classes en fournissant les fonctions libres équivalentes, ce qui a pour but d'offrir plus de flexibilité (et, accessoirement, de permettre la mise en place de certains concepts qui ont été ajoutés depuis ;) )

      Mais, ce qu'il faut retenir de tout cela, c'est bel et bien qu'il n'y a aucune différence entre utiliser std::size(container) et utiliser container.size(), tout comme il n'y  a aucune différence à utiliser std::begin(container) et std::end(container) et utiliser container.begin() / container.end() (ainsi que d'autres fonctions me semble-t-il).

      Ces nouvelles possibilités permettent, tout simplement, d'écrire un code qui sera plus "cohérent" dans le cas où il fait déjà appel à de "nombreuses" fonctions libres ;)

      • 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
        10 août 2020 à 16:08:11

        Merci pour votre réponse complète, le sujet est résolu.

        Bonne journée.

        • Partager sur Facebook
        • Partager sur Twitter
          10 août 2020 à 16:49:52

          Je pinaille, je vais revenir sur l'histoire.

          C'est marrant j'avais ressorti mon article dans linuxfr aujourd'hui, pour retrouver un lien: https://linuxfr.org/news/cpp17-libere-size-data-et-empty

          Dedans j'y avais repris une citation d'Alexander Stepanov, le concepteur de la STL, qui avait d^u faire des concessions pour que la STL soit intégrée dans la future SL (Standard Library) du C++. Je la reprends

          > « While we could make a member function to return length, it is better to make it a global friend function. If we do that, we will be able eventually to define the same function to work on built‐in arrays and achieve greater uniformity of design. I made size into a member function in STL in an attempt to please the standard committee. I knew that begin, end and size should be global functions but was not willing to risk another fight with the committee. In general, there were many compromises of which I am ashamed. It would have been harder to succeed without making them, but I still get a metallic taste in my mouth when I encounter all the things that I did wrong while knowing full how to do them right. Success, after all, is much overrated. I will be pointing to the incorrect designs in STL here and there: some were done because of political considerations, but many were mistakes caused by my inability to discern general principles. »-- Note on Programming (http://stepanovpapers.com/notes.pdf)

          NB: Stepanov se défend dans d'autres interviews que la STL soit de conception OO.

          Sinon, pour en revenir à la question initiale, dans une fonction template, `size(conteneur)`  (sans std:: devant) sera plus souple, nonobstant le `using std::size();` qui va bien.

          • Partager sur Facebook
          • Partager sur Twitter
          C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
            10 août 2020 à 19:21:44

            Merci pour la petite histoire, c'était intéressant mais ça veut dire quoi au juste "size(conteneur) sera plus souple" ? .size gère mieux les erreurs ?
            • Partager sur Facebook
            • Partager sur Twitter
              10 août 2020 à 21:21:31

              une explication ici: https://jonathanpoelen.github.io/2013/07/utilisation-de-swap-et-des-fonctions-utilitaires-en-general/

              Le principe (ADL) sur lequel se reposent les fonctions libres comme celle-ci part d'une bonne intention, mais je trouve que la mise en pratique est problématique sur plusieurs aspects:

              • Il faut utiliser un using avant utilisation, très peu de personne le font ou en comprennent la raison.
              • Cela ne repose pas sur des interfaces clairement définit, c'est implicite. On peut par inadvertance utiliser la fonction d'un autre namespace sans le faire exprès (donc un code peu magiquement ne plus fonctionner parce que fonction du même nom est apparue dans tel ou tel namespace).
              • C'est la merde dès que plusieurs types différents rentrent en jeu (tous les compilateurs ne se comportent pas de la même manière).
              • Partager sur Facebook
              • Partager sur Twitter

              container.size() ou std::size(container)

              × 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