Effectivement, pour visual par expl, il utilise le support du compilo pour les traits (__is_pod en l'occurrence). Et là, plus de méta prog, c'est du dur !
Version imprimable
Effectivement, pour visual par expl, il utilise le support du compilo pour les traits (__is_pod en l'occurrence). Et là, plus de méta prog, c'est du dur !
Tiens d'ailleurs, à propos de méta-programmation, cela faisait des années que je n'avais jamais rien bitté à la métaprog avant de soudainement recevoir une révélation cosmique grâce à cet article :
What Does Haskell Have to Do with C++?
Pourquoi personne n'avait jamais fait d'article aussi clair et simple avant ? :(
oufti 8O
:applo: :ccool:
Eh bien merci les gars.
Je connaissais un peu les boost::call_traits, voilà que je vais pouvoir affronter les type_traits désormais ;)
Mais, c'est quoi POD ? J'ai cru comprendre que c'est une structure "minimaliste", i.e. dont les membres sont eux-mêmes POD ou primitifs et dont les méthodes éventuelles sont non virtuelles, et pas de constructeur ni de destructeur explicites.
POD pour plain' old data, ça veut dire comme tu l'as dis que c'est soit un type primitifs soit une structure composé uniquement de type eux mêmes pod. les structs au sens C, les primitifs etc.
et :Citation:
Envoyé par The norme
[EDIT] grilled:aie:Citation:
Envoyé par The norme
Je rajoute juste qu'un type POD peut avoir des fonctions membres mais pas d'opérateur= ou de destructeur défini (ni de fonctions virtuelles bien sûr). La chose que j'oublie tout le temps est est-ce qu'une structure qui dérive d'une structure POD tout en respectant les critères est elle-même POD ? J'aurais tendance à dire non.
std::string n'est pas POD alors. Et toute structure contenant des std::string ne l'est pas non plus.
Comme tu dis les PODs sont donc des struct "C like".
Je me demande dans quel cas ça peut-être utile ce genre d'info.
L'inconvénient est la notion de "constructeur trivial": Ceci n'est pas considéré comme trivial:
Donc, on ne peut pas utiliser le raccourci return st_testPod2(42); si on veut que la structure soit POD (mais bon, on peut facilement faire une fonctionpour ça).Code:
1
2
3
4
5
6
7 struct st_testPod2 { int titi; explicit st_testPod2() : titi() {} explicit st_testPod2(int titi) : titi(titi) {} };
Merci.Citation:
Envoyé par Envoyé par The norme
Mais c'est le genre de prose qui dépasse mes capacités intellectuelles. J'ai beau lire 10 fois, ça reste incompréhensible pour moi :aie:
C'est là qu'on se dit qu'une image ou (un exemple) et son contraire valent 1000 mots ;)
Par exemple dans la STL de VS ou celle de GCC un appel à std::copy peut être optimisé en memove si le type pointé par l'itérateur est un pod.
Le code de la STL de gcc est relativement facile à suivre (comparé à celui de visual :aie:)
std::copy appelle tout d'abord __copy_move_a() qui va déterminer si le type est un pod ou non :
Si non, alors __simple == false, et on tombe au final sur une boucle for :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 template<bool _IsMove, typename _II, typename _OI> inline _OI __copy_move_a(_II __first, _II __last, _OI __result) { typedef typename iterator_traits<_II>::value_type _ValueTypeI; typedef typename iterator_traits<_OI>::value_type _ValueTypeO; typedef typename iterator_traits<_II>::iterator_category _Category; const bool __simple = (__is_pod(_ValueTypeI) && __is_pointer<_II>::__value && __is_pointer<_OI>::__value && __are_same<_ValueTypeI, _ValueTypeO>::__value); return std::__copy_move<_IsMove, __simple, _Category>::__copy_m(__first, __last, __result); }
Par contre si __simple = true, c'est un memmove :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 template<> struct __copy_move<false, false, random_access_iterator_tag> { template<typename _II, typename _OI> static _OI __copy_m(_II __first, _II __last, _OI __result) { typedef typename iterator_traits<_II>::difference_type _Distance; for(_Distance __n = __last - __first; __n > 0; --__n) { *__result = *__first; ++__first; ++__result; } return __result; } };
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 template<bool _IsMove> struct __copy_move<_IsMove, true, random_access_iterator_tag> { template<typename _Tp> static _Tp* __copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result) { __builtin_memmove(__result, __first, sizeof(_Tp) * (__last - __first)); return __result + (__last - __first); } ;
Joli ! :D
Au fait, pour savoir si un type est primitif, suffit-il d'utiliser __is_class() ? (et donc ==false)
EDIT: je me répond: pas tout à fait. Les références et pointeurs répondent aussi "false" à la question.
Arzar montrait l'exemple d'implémentation de GCC pour montrer l'utilité de ce genre d'info. Le code est donc le code de l'implémentation de la STL utilisée par GCC. A ce titre __is_class n'est pas standard et dépend du compilateur (ici, GCC).
Il faut attendre C++0x pour avoir des classes traits standards et en particulier un std::is_class.
On peut d'ailleurs attirer l'attention de tous sur le fait que, de manière générale, tout ce qui est préfixé par __ est propre à l'implémentation faite par les développeurs et n'est donc, par définition, ni standard ni garanti avec d'autres implémentations, que ce soit du point de vue du fournisseur ou du point de vue de la version...
OK, bien compris.
A partir du moment où autant GCC que MSVC supporte "ces petits machins" (__is_pod, __is_class), il n'y a pas trop de soucis à se faire. Il sera toujours temps de faire un "find and replace" dans l'ensemble du code pour les remplacer par leur équivalent std:: (il ne devrait pas y en avoir beaucoup...)
A conditions qu'ils aient le même sens pour les deux compilateurs...
Et ton code ne sera pas portable avec d'autres compilateurs.
Et pis, un jour il peuvent même disparaitre ou être renommé dans une nouvelle version de ces compilateurs. Bref beaucoup de contrainte et de maintenance que Boost.Trait t'épargne en attendant C++0x
Comme on essaye de le faire valoir:
Selon les besoins de ton projet, cela peut apporter pas mal de contraintes à la "portabilité" ;)
- Il n'y a pas que VC++ et Gcc (il y a les compilateurs intel, comeau et d'autres encore)
- ils peuvent exister dans la version 2.3 mais disparaitre dans la version 3 (voire, dans la version 2.4) et ne pas exister dans la version 1.9
- ...
J'ai cru comprendre que std::is_class et std::is_pod seront standards. Vous ai-je mal compris ?