Pour info, il y a un fil spécifique pour le dev web (et les outils qui en dérivent) :
https://forum.canardpc.com/threads/7...nt-des-cookies
Pour info, il y a un fil spécifique pour le dev web (et les outils qui en dérivent) :
https://forum.canardpc.com/threads/7...nt-des-cookies
Exact, j'ai fini par trouver une solution, avec readline avant le write.
Seul défaut, le mot de passe apparait en clair lorsqu'on le tape, mais bon.
- - - Mise à jour - - -
Oui, de toute façon j'ai une autre problématique maintenant, je vais poser la question là
Ha ok j'avais pas compris que tu voulais un prompt pour que tu puisses saisir le mot de passe manuellement.
Tu ne peux pas masquer le mot de passe de base avec readline, mais tu peux contourner le problème: https://stackoverflow.com/questions/...nodejs-console
Hello les canards. Je joue un peu avec les features de C++20, notamment les concepts (avec clang11). Je suis tombé sur un comportement un peu bizarre, qui est peut-être dû à l'aspect un peu expérimental de C++20, ou à mon incompréhension (plus probable).
J'ai le code suivant ou j'ai une classe de base qui sérialise/désérialise de façon simple (je prend/mets sizeof(Structure) depuis/dans le stream), sauf si la classe a un membre statique "custom_struct_size", auquel cas je mets/prends le nombre de bytes spécifiés par ce membre statique. Ca donne un truc comme :
La blague, c'est que quand j'ai un struct A qui hérite de SerDes<A> et qui a un membre "custom_struct_size"Code:template <typename T> concept custom_serdes_size = requires(T e) { T::custom_struct_size } -> std::same_as<size_t>; }; template<typename UnderlyingType> struct SerDes { void deserialize(std::istream & input) { if constexpr(custom_serdes_size<UnderlyingType>) { input.read((char*) this, UnderlyingType::custom_struct_size); } else { input.read((char*) this, sizeof(UnderlyingType)); } } void serialize(std::ostream & output) { if constexpr(custom_serdes_size<UnderlyingType>) { output.write((char*) this, UnderlyingType::custom_struct_size); } else { output.write((char*) this, sizeof(UnderlyingType)); } } };
eh bien la fonction serialize() de SerDes<A> prends la version du code qui est dans le else, donc ignore le concept. Par contre, si j'écris mon concept comme ceci :Code:struct A : public SerDes<A> { int a; int b; int c; //Pour ne ser/des que a et b static constexpr size_t custom_struct_size = sizeof(a) + sizeof(b); };
Eh ben là ça fonctionne. Est-ce que j'ai raté un truc sur les concepts et on ne peut pas s'en servir pour tester un membre (enfin sauf à tricher comme je l'ai fait) ?Code:template <typename T> concept custom_serdes_size = requires(T e) { { 0 + T::custom_struct_size } -> std::same_as<size_t>; };
Edit : j'ai changé mes couleurs
Dernière modification par Thamior ; 15/02/2022 à 17h47.
Envoyé par François
Il faudrait vérifier les règles exactes pour la déduction de type, mais peut-être que T::custom_struct_size donne le type "size_t &" (c'est une lvalue), alors que qu'avec le "0 +", tu en fais une prvalue. same_as est donc peut-être trop strict, essaye quelque chose de plus tolérant comme convertible_to.
PS: tes couleurs sont illisibles avec un thème clair.
PPS: Pour la déduction de type c'est équivalent à decltype((expr)), donc c'est bien ça (mais j'avais oublié un const).
Code:static_assert(std::is_same_v<decltype((A::custom_struct_size)), size_t>); // fail static_assert(std::is_same_v<decltype((A::custom_struct_size)), size_t &>); // fail static_assert(std::is_same_v<decltype((A::custom_struct_size)), const size_t &>); // ok static_assert(std::is_convertible_v<decltype((A::custom_struct_size)), size_t>); // ok
Dernière modification par Cwningen ; 15/02/2022 à 17h39.
Bingo ! Ca fonctionne avec convertible_to<size_t>. Par contre ça ne fonctionne pas avec same_as<size_t&> ou same_as<const size_t&>, donc je ne sais pas très bien quel type exact done T::custom_struct_size (en tout cas rien d'intuitif).
Dernière modification par Thamior ; 15/02/2022 à 20h06.
Envoyé par François
Chez moi (g++ (GCC) 11.2.1 20211203 (Red Hat 11.2.1-7)), tous les exemples suivants fonctionnent avec A.
(au passage "(T e)" est inutile, puisque tu n'utilises pas "e")Code:template <typename T> concept custom_serdes_size = std::same_as<const size_t &, decltype((T::custom_struct_size))>; template <typename T> concept custom_serdes_size = std::is_same_v<const size_t &, decltype((T::custom_struct_size))>; template <typename T> concept custom_serdes_size = requires (T e) { { T::custom_struct_size } -> std::same_as<const size_t &>; };
Hmm, je vais retester demain, car les "vraies" structures que j'utilise ne sont pas plus compliquées que la structure A que j'ai donné en exemple (c'est complètement POD).
En tout cas je n'aurais pas pensé aux deux premières versions qui sont un peu plus compactes, merci !
Bien vu, un reste d'un copié collé sans aucun doute
EDIT, : Bon, je viens de tester, et pour que ça fonctionne chez moi (Ubuntu clang version 11.0.0-2~ubuntu20.04.1), il faut mettre std::same_as<const size_t, decltype((T::custom_struct_size))>; Je pense que je vais me rabattre sur std::is_convertible pour éviter les surprises...
RE-EDIT : Je corrige, ton code fonctionne bien, c'est moi qui ne connaissait pas la différence entre decltype(X) et decltype((X)) et qui avait omis les doubles parenthèses dans mon code. Pas sûr d'avoir bien compris, mais j'y travaille.
Dernière modification par Thamior ; 15/02/2022 à 20h37.
Envoyé par François
Plus compactes mais pas forcément plus lisibles, surtout ici avec le decltype à doubles parenthèses. C'était surtout parce que c'était plus proche de mes static_assert, et que je n'étais pas sur que c'était parfaitement équivalent.
C'est plus intéressant si ton concept n'est qu'un combinaison de concepts/type_traits (par exemple "concept a_ou_b = a<T> || b<T>")
Le decltype à double parenthèses ne semble pas nécéssaire (si on enlève le "&") :
En tout cas ça fait ce que je veuxCode:template <typename T> concept custom_serdes_size = std::same_as<const size_t, decltype(T::custom_struct_size)>;
Envoyé par François
Petite question C++ :
J'ai rencontré un cas qui fonctionne et qui pour moi ne devrait pas ...
Pour moi le code devrait crasher à B puisqu’à ce moment là la classe est incomplète, pourtant ça semble compiler et fonctionner sans problème ...Code:template <class T> B; template <class T> A { B<T> truc; } template <class T> B { int bidule; T bloup; }
J'ai un petit doute sur le fait qu'étant des templates, leur taille n'est pas calculée à ce moment là du programme mais plutôt durant leur usage dans le code. Mais je n'arrive pas à voir comment le compilateur se sort du méli-mélo même ainsi.
Je suppose que tu as oublié des class/struct devant A et B.
Le compilateur essaye de ne pas trop se poser de question tant que le type n'est pas instancié. Si tu instancies plus tôt, tu as bien un problème.
Code:template <class T> struct B; template <class T> struct A { B<T> truc; }; template struct A<int>; template <class T> struct B { int bidule; T bloup; };Code:nilsou.cpp: Dans l'instanciation de « struct A<int> » : nilsou.cpp:8:17: requis depuis ici nilsou.cpp:5:14: erreur: « A<T>::truc » a un type incomplet 5 | B<T> truc; | ^~~~ nilsou.cpp:1:27: note: déclaration de « struct B<int> » 1 | template <class T> struct B; | ^
Ouais c'est ce que tu dis Nilsou, ça fonctionne uniquement vu que c'est des templates et que le compilateur va faire la résolution au dernier moment. Donc à ce moment B sera une classe complète.
Donc:
est valideCode:template<class T> class B; template<class T> class A { B<T> truc; }; template<class T> class B { };
En revanche:
n'est pas valide.Code:class B; class A { B truc; // B is incomplete }; class B { };
Mais c'est un problème artificiel car il suffit de très simplement:
Ce que le compilo peut faire avec les templates vu que les templates sont résolus tardivement selon les instances qui les utilisent. Donc il aura la définition de B à ce moment.Code:class B; class B { }; class A { B truc; // B is complete };
- - - Mise à jour - - -
Après sinon, et de manière plus pratique, si tu veux faire des classes interdépendantes, tu peux utiliser les forward declaration comme ça:
Code:class A; class B { public: int known_member; void use(A a); }; class A { B truc; }; void B::use(A a) { }
Oui ok. Effectivement j'avais oublié les class devant A et B.
Merci pour vos réponses.
Je suis étonné par ton exemple final Kamikaze, c'est vrai que d'habitude je ne me pose pas trop la question (parce que j'ai une façon de faire et au final je converge toujours sur ça, ça marche, et j'ai un peu oublié le détail) mais vu que j'ai du corriger pas mal d'erreurs aujourd'hui je me poses la question du détail
Donc ici, le compilo n'a t-il pas besoin dès le prototype de use du type complet de A ?
Yep
Donc ton exemple ne fonctionne pas si ?
Si, rho suffit de le copier coller...
- - - Mise à jour - - -
https://godbolt.org/z/fbqzc35jE
Ah my bad j'avais mal lu ton message "n'a t-il pas" j'ai lu "n'a pas"
Donc non, y'a pas besoin, ça marche, click, click mon lien
Ok je te crois haha, mais pourquoi ça marche ?
edit : bon je viens de voir que la taille d'une fonction d'une classe en C++ est de 0 : https://nolowiz.com/size-of-cpp-classes/
Donc j'en déduit que le code n'a en effet nul besoin de calculer la taille de A, quelque soit la fonction et cie.
Je m'attendais à ce qu'en interne il y ait au moins un pointeur (mais ça aurait marché quand même puisque pointeur = taille fixe) mais au final même pas ...
C'est le compilo qui gère tout en sous main en fait ? Les fonctions membres n'ont pas de véritables existence dans la classe comme on le faisait en trichant en (très vieux) C en rajoutant des pointeurs de fonctions dans une structure.
Un prototype est une déclaration, ça ne définit rien. Pas besoin que les types de retour ou des paramètres soient complets. Et ça vaut aussi pour les méthodes virtuelles, il n'y a pas besoin de type complet pour définir un pointeur.
Voilà, comme une interface, conceptuellement quoi, tu déclares mais y'a pas l'implem, tout est ok
Ok c'est noté, c'est plus clair, merci.
J'ai besoin de vos éclaircissements. Je dev en windows avec des lib pour la première fois et j'ai un peu du mal à comprendre l'association .lib avec les .dll .
De ce que je comprends les .lib sont l'équivalent des .a sous linux tandis que les .dll sont plutôt l'équivalent des lib dynamique façon .so. MAIS les .lib peuvent aussi être associé à des dll ?
Comment ça se passe dans ce dernier cadre ? le compilateur va chercher la dll pour inclure le tout en linkage statique dans l’exécutable ou alors il aura besoin de la dll. Et comment distinguer un .lib d'un autre alors ? Même ligne de commande à la compil et deux comportements différents ?
Je demande ça parce que j'ai un programme compilé avec gcc sous windows et la .lib en brut qui lui est donné pour le linkage. Mais le programme crash sans la DLL dans le repertoire. Donc d'une manière ou d'une autre j'en déduit que le lien s'est fait en dynamique. Mais l'ensemble me parait assez flou. (et comment le savoir à la compilation ? )
Dernière modification par Nilsou ; 02/03/2022 à 09h42.
Bienvenu dans "l'enfer" des lib sous windows.
En effet un .lib peut être l'équivalent d'un .a, mais une .dll aura toujours un .lib associé pour permettre le linkage.
Si ton .lib est une lib statique (.a), alors c'est auto suffisant, il contient les exports et le code pré compilé
Si ton .lib est associé à une .dll, imagine le comme un fichier qui contient les symboles qu'exporte publiquement ta .dll. Dans le temps c'était des .def, qui n'étaient plus ou moins que des textes avec la liste des symboles, mais il me semble que c'est encore utilisable de nos jours.
La programmation est une course entre le développeur, qui s’efforce de produire des applications à l’épreuve des imbéciles, et l’univers qui s’efforce de produire de meilleurs imbéciles... L’univers a une bonne longueur d’avance !!!
Hello !Est-ce que quelqu'un utilise CMake / vcpkg sous Linux ? Je voudrais commencer un petit projet mais j'avoue que je galère à intégrer certaines lib. Je détaillerai si il y a des utilisateurs pour pas poluer.
Avec Visual Studio, y'a un outil nommé dumpbin qui permet d'aller fouiller dans les .lib/.dll et sûrement d'autres choses
Si c'est une lib static, ca va dump toutes les directives (charabia pour le linker de visual studio)Code:dumpbin /DIRECTIVES <path to lib>
Par contre j'ai pas tant utilisé gcc sous windows, donc je ne saurai pas te dire.
La programmation est une course entre le développeur, qui s’efforce de produire des applications à l’épreuve des imbéciles, et l’univers qui s’efforce de produire de meilleurs imbéciles... L’univers a une bonne longueur d’avance !!!
Hum, malheureusement je ne dev pas avec visual studio. J'aurais aimé avoir dans l'idéal une commande externe mais merci pour l'info.
Pour gcc c'est plus une question générale : qu'on soit sous linux ou windows ce serait pas mal d'avoir un retour du linker sur le type de lien qu'il a créé...
J'avais fait un long post d'insulte à l'époque sur comment intégrer cmake + vcpkg (+vulkan accessoirement) sur windows. Faut que je m'y remette je vais en avoir besoin aussi.
Et faut que je remette la main dessus c'est plus haut dans le topac