Según cppreference.com size_t
se define en varios encabezados, a saber
<cstddef>
<cstdio>
<cstring>
<ctime>
Y, desde C ++ 11, también en
<cstdlib>
<cwchar>
En primer lugar, me pregunto por qué es así. ¿No está esto en contradicción con el principio DRY ? Sin embargo, mi pregunta es:
¿Cuál de los encabezados anteriores debo incluir para usar size_t
? ¿Importa en absoluto?
<cstddef>
parastd::size_t
std::size_t
y el OP no abogaba por el uso de funciones C heredadas, solo observando la cita sobre ellos compartiendo el typedef. Dudo que alguien que lea este hilo sea engañado al usar tipos / funciones heredados debido a esto, pero si quieres estar seguro de que no lo hacen, ¡entonces es justo!Respuestas:
Suponiendo que quisiera minimizar las funciones y los tipos que estaba importando, iría con,
cstddef
ya que no declara ninguna función y solo declara 6 tipos. Los demás se centran en dominios particulares (cadenas, tiempo, IO) que pueden no importarle.Tenga en cuenta que
cstddef
solo garantiza definirstd::size_t
, es decir, definirsize_t
en el espacio de nombresstd
, aunque puede proporcionar este nombre también en el espacio de nombres global (efectivamente, sin formatosize_t
).Por el contrario,
stddef.h
(que también es un encabezado disponible en C) garantiza definirsize_t
en el espacio de nombres global, y también puede proporcionarstd::size_t
.fuente
size_t
decstddef
es igual y siempre será igual que los demás? Parece que debería haber un archivo de encabezado común con definiciones comunes comosize_t
...cstddef
.<cstddef>
, o todos podrían incluir algún encabezado interno que solo definasize_t
.csttddef
respuesta es un error tipográfico? ¿Quizáscstddef
se refiere?De hecho, la sinopsis (incluida en el estándar C ++) de varios encabezados se incluye específicamente
size_t
, así como otros encabezados definen el tiposize_t
(según el estándar C, ya que los<cX>
encabezados son solo<X.h>
encabezados ISO C con cambios notados dondesize_t
no se indica la eliminación de ).Sin embargo, el estándar C ++ se refiere a
<cstddef>
la definición destd::size_t
Por lo tanto, y debido al hecho de que
<cstddef>
solo introduce tipos y no funciones, me quedaría con este encabezado para que estéstd::size_t
disponible.Tenga en cuenta algunas cosas:
El tipo de
std::size_t
se puede obtenerdecltype
sin incluir un encabezadoSi planea introducir un typedef en su código de todos modos (es decir, porque escribe un contenedor y desea proporcionar un
size_type
typedef), puede usar los operadores globalsizeof
,sizeof...
oralignof
para definir su tipo sin incluir ningún encabezado, ya que esos operadores regresanstd::size_t
por definición estándar y puede usardecltype
en ellos:std::size_t
no es per se globalmente visible, aunque las funciones constd::size_t
argumentos sí lo son.Las funciones de asignación y desasignación globales declaradas implícitamente
NO introduzca
size_t
,std
ostd::size_t
yEl usuario no puede redefinir,
std::size_t
aunque es posible tener múltiples typedefs que se refieran al mismo tipo en el mismo espacio de nombres.Aunque, la ocurrencia de múltiples definiciones de
size_t
insidestd
es perfectamente válida según 7.1.3 / 3 , no se permite agregar ninguna declaraciónnamespace std
según 17.6.4.2.1 / 1 :Agregar un typedef apropiado para
size_t
el espacio de nombres no viola 7.1.3 pero viola 17.6.4.2.1 y conduce a un comportamiento indefinido.Aclaración: Trate de no malinterpretar 7.1.3 y no agregue declaraciones o definiciones
std
(excepto en algunos casos de especialización de plantilla donde un typedef no es una especialización de plantilla). Extendiendo elnamespace std
fuente
std
no sea válido porque las typedefs duplicadas son ilegales. Declaro que es ilegal porque simplemente no puede agregar definicionesnamespace std
, sin importar si serían legales.Todos los archivos de encabezado de biblioteca estándar tienen la misma definición; no importa cuál incluya en su propio código. En mi computadora, tengo la siguiente declaración en formato
_stddef.h
. Este archivo está incluido en todos los archivos que enumeró.fuente
size_t
en primer lugar?size_t
. Puede definirlo de manera más portátil comousing size_t = decltype( sizeof( 42 ) )
. Pero no es necesario, ya que<stddef.h>
tiene un costo casi nulo.Podrías prescindir de un encabezado:
Esto se debe a que el estándar C ++ requiere:
En otras palabras, el estándar requiere:
También tenga en cuenta que está perfectamente bien hacer esta
typedef
declaración en elstd
espacio global y en el espacio de nombres, siempre que coincida con todas las demástypedef
declaraciones del mismo typedef-name (se emite un error del compilador en declaraciones que no coinciden).Esto es porque:
§7.1.3.1 Un typedef-name no introduce un nuevo tipo como lo hace una declaración de clase (9.1) o una declaración de enumeración.
§7.1.3.3 En un ámbito que no sea de clase dado,
typedef
se puede usar un especificador para redefinir el nombre de cualquier tipo declarado en ese ámbito para hacer referencia al tipo al que ya se refiere.A los escépticos que dicen que esto constituye una adición de un nuevo tipo en el espacio de nombres
std
, y tal acto está explícitamente prohibido por el estándar, y esto es UB y eso es todo; Debo decir que esta actitud equivale a ignorar y negar una comprensión más profunda de los problemas subyacentes.El estándar prohíbe agregar nuevas declaraciones y definiciones en el espacio de nombres
std
porque al hacerlo el usuario puede hacer un lío de la biblioteca estándar y dispararse. Para los escritores estándar, era más fácil dejar que el usuario se especializara en algunas cosas específicas y prohibir hacer cualquier otra cosa por si acaso, en lugar de prohibir todo lo que el usuario no debería hacer y arriesgarse a perderse algo importante (y esa pierna). Lo hicieron en el pasado cuando requerían que ningún contenedor estándar se instanciara con un tipo incompleto, mientras que, de hecho, algunos contenedores podrían funcionar bien (ver The Standard Librarian: Containers of Incomplete Types por Matthew H. Austern ):Dado que las reglas del lenguaje requieren
std::size_t
ser exactasdecltype(sizeof(int))
, hacernamespace std { using size_t = decltype(sizeof(int)); }
es una de esas cosas que no rompen nada.Antes de C ++ 11 no
decltype
había forma de declarar el tipo desizeof
resultado en una declaración simple y, por lo tanto, no existía una buena cantidad de plantillas.size_t
alias diferentes tipos en diferentes arquitecturas de destino, sin embargo, no sería una solución elegante agregar un nuevo tipo integrado solo por el resultado desizeof
, y no hay typedefs estándar integrados. Por lo tanto, la solución más portátil en ese momento era poner unsize_t
alias de tipo en algún encabezado específico y documentarlo.En C ++ 11 ahora hay una forma de escribir ese requisito exacto del estándar como una simple declaración.
fuente
size_t
!" Un minuto más tarde, Mary dijo: "¡Dios mío! ¡Hay 7 definiciones desize_t
encabezados de biblioteca estándar y un encabezado de proyecto que Tom está editando! ¡Probablemente hay más en las bibliotecas de terceros!" xkcd.com/927size_t
, esto no responde a la pregunta real del OP: es como si le pidiera el encabezado dondeFILE
se declara y usted sugeriría escribir uno propio.