Crunchez vos adresses URL
|
Calculez la conso électrique de votre PC
|
Hébergez vos photos
Page 66 sur 66 PremièrePremière ... 1656585960616263646566
Affichage des résultats 1 951 à 1 966 sur 1966
  1. #1951
    Je ne sais pas comment fonctionne Gson en interne, mais si c'est comme XStream (un sérialiseur/désérialiseur de XML) les instanciations se font d'office via un constructeur 'vide' (même s'il n'existe pas) et les initialisations de champs se font par introspection sans passer par les setteurs.

    Pour éviter les ennuis et les bricolages j'ai l'impression que c'est plus simple de passer par un Gson Instance Creator, comme conseillé ici https://futurestud.io/tutorials/gson...stance-creator (premier lien au pif trouvé sur Google).

  2. #1952
    Je viens de découvrir que ce code est valide avec MSVC :
    Code:
    struct { int a; double b; } test() {
      return { 1, 2.0 };
    }
    
    int main() {
        auto[a, b] = test();
    }
    La partie struct vers structured binding est valide en c++ 17.

    La partie importante ici est la structure anonyme définie en même temps que la fonction.
    Je viens de voir que c'est plus une erreur de la part de l'équipe MSVC qu'autre chose mais que c'est en cours d'étude (Il me semble, je suis pas encore hyper à l'aise avec les proposals, TS et autres TR... )

    Need cette fonctionnalité !

  3. #1953
    J'ai vaguement vu que les tuples avaient un support de plus en plus renforcé, mais là ça va plus loin encore?
    Faut que je trouve le temps d'attaquer 14 et 17

  4. #1954
    Citation Envoyé par Raplonu Voir le message
    Je viens de découvrir que ce code est valide avec MSVC :
    Code:
    struct { int a; double b; } test() {
      return { 1, 2.0 };
    }
    
    int main() {
        auto[a, b] = test();
    }
    La partie struct vers structured binding est valide en c++ 17.

    La partie importante ici est la structure anonyme définie en même temps que la fonction.
    Je viens de voir que c'est plus une erreur de la part de l'équipe MSVC qu'autre chose mais que c'est en cours d'étude (Il me semble, je suis pas encore hyper à l'aise avec les proposals, TS et autres TR... )

    Need cette fonctionnalité !
    C'est pas très différent d'un tuple au final. La seule différence c'est que tu nommes les membres mais que tu te retrouves avec un type anonyme (pas toujours très pratique, tu risques d'avoir besoin de std::invoke_result_t<test> à un moment).

    La proposition semble surtout réfléchir sur les problèmes posés par cette idée. Ça va prendre du temps pour avoir une réponse définitive.

    @vectra, regarde au moins le C++14, c'est pas révolutionnaire mais ça améliore bien le C++11.

  5. #1955
    C'est vraiment tout con, mais je trouve l'idée de voir le nom des membres directement dans la signature de la fonction apporte beaucoup en lisibilité et en productivité.

    Avec un IDE, tu passes la souris sur la fonction et tu sais exactement comment prendre en charge ce qui est retourné.

    L'idée d'utiliser une struct anonyme pousse le concept de : je renvois des choses qui n'ont pas vocation à rester ensemble. Si un nom représente bien ce que tu renvois et/ou que stocker le résultat tel quel a du sens, alors oui, c'est pas adapté.

    L'exemple le plus simple qui me vient à l'esprit : un résultat et un code d'erreur :

    Le cas classique, lourd à écrire avec un nom de type de retour à la noix. Il faut 2 étapes pour connaitre le contenu de ce que retourne get_size (Chercher le type de retour de la fonction, puis le contenu de ce type).

    Code:
    struct HandleAndError {
        int handle;
        int error;
    };
    
    HandleAndError get_handle();
    Léger à écrire mais il faut lire la doc pour savoir qui est qui.
    Code:
    std::tuple<int, int> get_handle();
    Dans ce dernier cas, tu sais tout de suite qui est qui, et tu informes indirectement l'utilisateur de ne pas stoker la structure.
    Code:
    struct { int handle; int error; } get_handle();
    La proposition semble surtout réfléchir sur les problèmes posés par cette idée. Ça va prendre du temps pour avoir une réponse définitive.
    Flute

  6. #1956
    Pour le renvoi d'un résultat ou d'une erreur, il y a std::expected en projet (pas sûr que ce soit prêt pour C++20 malheureusement), et ça devrait être bien mieux avec les opérations sur les monades.

  7. #1957
    C++ va devenir aussi bien qu'OCaml

    Faut absolument que je me mette à jour sur C++ j'ai un gros retard... Mes connaissances pré datent C++11. Vous connaissez de bons bouquins pour des gens niveau intermédiaire ?

  8. #1958
    Citation Envoyé par newbie06 Voir le message
    C++ va devenir aussi bien qu'OCaml
    Peu de chances, sans un cassage de backward compat'
    Because you're young, sharp as a knife
    You need that buzz to come alive

  9. #1959
    Citation Envoyé par Raplonu Voir le message
    C'est vraiment tout con, mais je trouve l'idée de voir le nom des membres directement dans la signature de la fonction apporte beaucoup en lisibilité et en productivité.

    Avec un IDE, tu passes la souris sur la fonction et tu sais exactement comment prendre en charge ce qui est retourné.

    L'idée d'utiliser une struct anonyme pousse le concept de : je renvois des choses qui n'ont pas vocation à rester ensemble. Si un nom représente bien ce que tu renvois et/ou que stocker le résultat tel quel a du sens, alors oui, c'est pas adapté.

    L'exemple le plus simple qui me vient à l'esprit : un résultat et un code d'erreur :

    Le cas classique, lourd à écrire avec un nom de type de retour à la noix. Il faut 2 étapes pour connaitre le contenu de ce que retourne get_size (Chercher le type de retour de la fonction, puis le contenu de ce type).

    Code:
    struct HandleAndError {
        int handle;
        int error;
    };
    
    HandleAndError get_handle();
    Léger à écrire mais il faut lire la doc pour savoir qui est qui.
    Code:
    std::tuple<int, int> get_handle();
    Dans ce dernier cas, tu sais tout de suite qui est qui, et tu informes indirectement l'utilisateur de ne pas stoker la structure.
    Code:
    struct { int handle; int error; } get_handle();
    (
    J'ai du mal à voir l’intérêt de ces formalismes ...
    OK il y a un micro-gain de lisibilité dans le code, mais il est, je trouve très faible... n'est-ce pas de l'enculage de mouche ? (respectueusement bien sur)

    Par exemple, le gain ne s'exprime pas si on a besoin de cette structure ailleurs (pour faire d'autres fonction du même type par exemple) et ou dans ce cas avoir une structure généraliste se vaut tout autant d'un point de vue lisibilité.
    Le gain sur la lisibilité dans les autres cas, lui, est très situationnel, n'importe quel IDE qui se respecte te donne le contenu de ton HandleAndError en un clic ... et si le code est bien organisé la structure n'est pas loin ou dans un header avec un nom évident (genre gestion_erreur.h )

    Enfin bon, il n'y a par contre que peu de raison que ce soit interdit, mais ça ne me donne pas trop envie de l'utiliser ^^.

  10. #1960
    Citation Envoyé par Nilsou Voir le message
    OK il y a un micro-gain de lisibilité dans le code, mais il est, je trouve très faible... n'est-ce pas de l'enculage de mouche ? (respectueusement bien sur)
    Oui, c'est très clairement un cas d'enculage de mouche. Mais c'est toute la beauté du C++, argumenter pendant 1000 ans sur des sujets que d'autres langages tranchent en 10 minutes (et finir avec des syntaxes du style obj.template call() ).

    Plus sérieusement, j'ai découvert ça aujourd'hui, et ça m'a refait penser au très bon talk de Kate Gregory où à 31 min elle aborde le sujet des fonctions avec plusieurs sorties.

    Rapidement, ce qu'elle dit (ce que j'ai compris) :

    Un nom te viens à l'esprit pour décrire ce que tu renvois ? -> À l'ancienne, on la déclare et on l'utilise.

    Si ce que tu renvois n'est rien d'autre que 2 entiers ou 3 chaines de caractères et un entier -> tuple & strutured bindings.

    Personnellement, je suis pas fan de cette dernière réponse ( À ceci près que cette solution est possible contrairement à ce que je propose ) . Et je trouve qu'une struct anonyme permet d'ajouter très facilement des informations extrêmement utiles sans perdre l'aspect strutured bindings.

    Code:
    std::tuple<std::string, std::string, std::string, int> fun1();
    
    struct { std::string name; std::string favoriteSinger; std::string bitCoinId; int captainAge; } fun2();
    Je trouve qu'on peut mettre ça en relation avec les arguments d'une fonction. On préfère quoi ?
    Code:
    void fun(std::string, std::string, std::string, int);
    
    void fun(NameAndFavoriteSingerAndBitCoinIdAndCaptainAge arg);
    
    void fun(std::string name, std::string favoriteSinger, std::string bitCoinId, int captainAge);

  11. #1961
    Il y a un lien entre le nom (de quoi ? de qui ?), le chanteur favori (de qui ?) et cet Id Bitcoin ? Je ne compte pas l'âge du capitaine qui devrait être une variable globale volatile, à moins que ce soit son age lors d'un évènement précis. Peut-être que ce lien mérite un nom, dans le type de retour ou dans le nom de la fonction. Si la fonction avait un meilleur nom, peut-être qu'on comprendrait le sens du tuple. C'est dur de discuter lisibilité sur des exemples bidons.

  12. #1962
    Figure paternelle de substitution Avatar de TiNitro
    Ville
    Capitale eud'chwal
    Oui c'est pratique (ça existe en C#), ça évite de se faire chier à créer une struct dans certains cas, mais on ne s'en sert pas tous les jours.
    D'autant que le jour ou tu veux renvoyer une information supplémentaire tu l'as dans l'os.

    Enfin bref je ne suis pas hyper fan, mais on utilise de temps à autre. Et VS aide bien.

  13. #1963
    Le seul truc que je trouve sympa sur les tuple et cie, c'est pas du tout dans ce genre d'utilisation, mais plutôt en profitant des fonctions associées (notamment les opérateurs) qui permettent souvent de s'économiser du travail.

    Genre si vous avez 3 entier a,b,c et 3 autres d,e,f et que vous voulez verifier que tout entier a,b,c est bien inférieur à tout les entiers d,e et f, ben il suffit décrire un truc comme tie(a,b,c)<tie(d,e,f) . En profitant du fait que les opérateurs sont déja écris ainsi (idem pour les égalités etc...)

    En dehors de ça, j'ai un peu de mal à les utiliser, je trouve ça pas très propre, mais bon, chacun ses habitudes ^^.

  14. #1964
    Citation Envoyé par Cwningen Voir le message
    Si la fonction avait un meilleur nom, peut-être qu'on comprendrait le sens du tuple. C'est dur de discuter lisibilité sur des exemples bidons.
    J'ai un exemple dans la std avec une méthode de std::map

    Code:
    template <class M>
    pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
    Le booléen représente quoi ? On doit lire la doc pour le savoir. Vrai et faux pour respectivement une insertion et un affectation. C'est pas incroyablement dur à comprendre mais le doute est permis.

    Code:
    template <class M>
    struct {iterator it, bool insertSuccsess } insert_or_assign(const key_type& k, M&& obj);
    Je trouve cette solution élégante.

    PS : Juste, histoire d'être claire, je suis pas un défenseur de cette fonctionnalité. je trouvais juste cette solution intéressante et fait apparaitre un concept que je ne connaissais pas en programmation : le nommage des sorties.

  15. #1965
    Celui-là est bien mieux en effet. Par contre j'aurais appelé le booléen "inserted", puisqu'il n'indique pas la réussite de la fonction. C'est aussi à comparer avec "pair<iterator, bool> insert(P&& value)" où le type de retour est le même mais n'a pas exactement le même sens. Dans les deux cas, l'itérateur retourné est valide quand le booléen est faux, donc ce n'est pas remplaçable par un optional<iterator>. Pour insert, j'aurais du mal à nommer l'itérateur, il a un sens différent suivant la valeur du booléen : inserted_or_existing_iterator, ça fait un peu long. Ici la structure anonyme se justifie parce que c'est dur de l'expliquer autrement que par l’agrégation de ses deux membres. Mais lire la doc, ce n'est pas un mal, c'est parfois dur de bien expliquer les fonctions avec quelques noms courts.

    Pour nommer les retours, il y a aussi la possibilité d'utiliser un pointeur/référence mutable en paramètre, ça se fait beaucoup en C. Par exemple, on peut imaginer: bool map_insert(map_t *map, void *value, map_iterator_t *position_out) (où position_out peut être nul si on n'est pas intéressé). Mais je ne crois pas que ce soit un style très apprécié en C++.

  16. #1966
    Citation Envoyé par William Vaurien Voir le message
    Je ne sais pas comment fonctionne Gson en interne, mais si c'est comme XStream (un sérialiseur/désérialiseur de XML) les instanciations se font d'office via un constructeur 'vide' (même s'il n'existe pas) et les initialisations de champs se font par introspection sans passer par les setteurs.

    Pour éviter les ennuis et les bricolages j'ai l'impression que c'est plus simple de passer par un Gson Instance Creator, comme conseillé ici https://futurestud.io/tutorials/gson...stance-creator (premier lien au pif trouvé sur Google).
    Je te remercie de Googler pour moi ... (j'avais trouvé ces vidéos, mais pas celle-ci en particulier, je m'y remets...)
    Citation Envoyé par Triz' Voir le message
    Un bon jeu de mots, c'est comme une bonne levrette. Il faut que ce soit un petit peu tiré par les cheveux.

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •