Selon cppreference.com size_t
est défini dans plusieurs en-têtes, à savoir
<cstddef>
<cstdio>
<cstring>
<ctime>
Et, depuis C ++ 11, également dans
<cstdlib>
<cwchar>
Tout d'abord, je me demande pourquoi c'est le cas. N'est-ce pas en contradiction avec le principe DRY ? Cependant, ma question est:
Lequel des en-têtes ci-dessus dois-je inclure pour utiliser size_t
? Est-ce vraiment important?
<cstddef>
pourstd::size_t
std::size_t
, et l'OP ne préconisait pas l'utilisation de fonctions C héritées, observant simplement la citation à propos du partage du typedef. Je doute que quiconque lisant ce fil soit induit en erreur en utilisant des types / fonctions hérités à cause de cela, mais si vous voulez être sûr qu'ils ne le font pas, alors assez bien!Réponses:
En supposant que je voulais minimiser les fonctions et les types que j'importais, j'irais avec
cstddef
car il ne déclare aucune fonction et ne déclare que 6 types. Les autres se concentrent sur des domaines particuliers (chaînes, temps, IO) qui peuvent ne pas vous intéresser.Notez que
cstddef
seules les garanties de définirstd::size_t
, c'est-à-dire de définirsize_t
dans l'espace de nomsstd
, bien qu'il puisse également fournir ce nom dans l'espace de noms global (effectivement, simplesize_t
).En revanche,
stddef.h
(qui est également un en-tête disponible en C) garantit de définirsize_t
dans l'espace de noms global, et peut également fournirstd::size_t
.la source
size_t
decstddef
est le même et sera toujours le même que les autres? On dirait qu'il devrait y avoir un fichier d'en-tête commun avec des définitions communes commesize_t
...cstddef
.<cstddef>
, ou ils pourraient tous inclure un en-tête interne qui définit simplementsize_t
.csttddef
réponse est-elle une faute de frappe? Peutcstddef
- être que cela veut dire?En fait, le synopsis (inclus dans la norme C ++) de plusieurs en-têtes inclut spécifiquement
size_t
ainsi que d'autres en-têtes définissent le typesize_t
(basé sur la norme C car les en-<cX>
têtes ne sont que des en- têtes ISO C<X.h>
avec des changements notés où la suppression desize_t
n'est pas indiquée).Le standard C ++ fait cependant référence à
<cstddef>
la définition destd::size_t
Par conséquent et en raison du fait que
<cstddef>
n'introduit que des types et aucune fonction, je m'en tiendrai à cet en-tête pour le rendrestd::size_t
disponible.Notez quelques points:
Le type de
std::size_t
peut être obtenu en utilisantdecltype
sans inclure d'en-têteSi vous avez l' intention de présenter un typedef dans votre code de toute façon (parce que vous écrivez un conteneur et que vous voulez fournir un
size_type
typedef) , vous pouvez utiliser les mondiauxsizeof
,sizeof...
ou lesalignof
opérateurs pour définir votre type sans inclure les en- têtes du tout depuis lces opérateurs retourstd::size_t
par définition standard et vous pouvez utiliserdecltype
sur eux:std::size_t
n'est pas en soi globalement visible bien que les fonctions avecstd::size_t
arguments le soient.Les fonctions d'allocation et de désallocation globales déclarées implicitement
NE PAS introduire
size_t
,std
oustd::size_t
etL'utilisateur ne peut pas redéfinir
std::size_t
bien qu'il soit possible d'avoir plusieurs typedefs faisant référence au même type dans le même espace de noms.Bien que l'occurrence de plusieurs définitions de
size_t
withinstd
soit parfaitement valide selon 7.1.3 / 3 , il n'est pas permis d'ajouter des déclarations ànamespace std
selon 17.6.4.2.1 / 1 :L'ajout d'un typedef pour
size_t
à l'espace de noms ne viole pas 7.1.3 mais viole 17.6.4.2.1 et conduit à un comportement indéfini.Clarification: essayez de ne pas mal interpréter 7.1.3 et n'ajoutez pas de déclarations ou de définitions
std
(à l'exception de quelques cas de spécialisation de modèle où un typedef n'est pas une spécialisation de modèle). Extension de lanamespace std
la source
std
est invalide car les typedef en double sont illégaux. Je déclare que c'est illégal parce que vous ne pouvez tout simplement pas ajouter de définitionsnamespace std
- peu importe si elles seraient légales.Tous les fichiers d'en-tête de bibliothèque standard ont la même définition; peu importe celui que vous incluez dans votre propre code. Sur mon ordinateur, j'ai la déclaration suivante au format
_stddef.h
. Ce fichier est inclus dans chaque fichier que vous avez répertorié.la source
size_t
en premier lieu?size_t
. Vous pouvez le définir de manière plus portable commeusing size_t = decltype( sizeof( 42 ) )
. Mais il n'y a pas besoin, car<stddef.h>
a un coût presque nul.Vous pourriez vous passer d'un en-tête:
En effet, la norme C ++ requiert:
En d'autres termes, la norme exige:
Notez également qu'il est parfaitement bien de faire cette
typedef
déclaration dans l'std
espace de noms global et dans , tant qu'elle correspond à toutes les autrestypedef
déclarations du même typedef-name (une erreur de compilation est émise sur les déclarations non correspondantes).Ceci est dû au fait:
§7.1.3.1 Un typedef-name n'introduit pas de nouveau type comme le fait une déclaration de classe (9.1) ou une déclaration enum.
§7.1.3.3 Dans une portée non-classe donnée, un
typedef
spécificateur peut être utilisé pour redéfinir le nom de tout type déclaré dans cette portée pour faire référence au type auquel il fait déjà référence.Aux sceptiques disant que cela constitue un ajout d'un nouveau type dans l'espace de noms
std
, et qu'un tel acte est explicitement interdit par la norme, et c'est UB et c'est tout là-dedans; Je dois dire que cette attitude revient à ignorer et à nier une compréhension plus profonde des problèmes sous-jacents.Le standard interdit l'ajout de nouvelles déclarations et définitions dans l'espace de noms
std
car, ce faisant, l'utilisateur peut faire un désordre de la bibliothèque standard et lui tirer dessus toute sa jambe. Pour les rédacteurs standard, il était plus facile de laisser l'utilisateur se spécialiser dans certaines choses spécifiques et interdire de faire quoi que ce soit d'autre pour faire bonne mesure, plutôt que d'interdire chaque chose que l'utilisateur ne devrait pas faire et risquerait de manquer quelque chose d'important (et cette étape). Ils l'ont fait dans le passé en exigeant qu'aucun conteneur standard ne soit instancié avec un type incomplet, alors qu'en fait certains conteneurs pourraient bien le faire (voir The Standard Librarian: Containers of Incomplete Types par Matthew H.Austern ):Étant donné que les règles linguistiques exigent
std::size_t
d'être exactesdecltype(sizeof(int))
, fairenamespace std { using size_t = decltype(sizeof(int)); }
est l'une de ces choses qui ne cassent rien.Avant C ++ 11, il n'y avait pas
decltype
et donc aucun moyen de déclarer le type desizeof
résultat en une seule instruction simple sans impliquer un grand nombre de modèles.size_t
alias différents types sur différentes architectures cibles, cependant, ce ne serait pas une solution élégante d'ajouter un nouveau type intégré uniquement pour le résultat desizeof
, et il n'y a pas de typedefs standard intégrés. Par conséquent, la solution la plus portable à l'époque était de mettresize_t
un alias de type dans un en-tête spécifique et de le documenter.En C ++ 11, il existe maintenant un moyen d'écrire cette exigence exacte de la norme comme une simple déclaration.
la source
size_t
!" Une minute plus tard, Mary a dit, "OMG! Il y a 7 définitions d'size_t
en-têtes de bibliothèque standard et un en-tête de projet que Tom est en train de modifier! Il y en a probablement d'autres dans les bibliothèques tierces!" xkcd.com/927size_t
, cela ne répond pas à la vraie question du PO: c'est comme si j'avais demandé l'en-tête oùFILE
est déclaré et que vous suggéreriez d'écrire le mien.