Solución:
Las reglas (que no cambiaron en C ++ 11):
- Reservado en cualquier ámbito, incluso para su uso como macros de implementación:
- identificadores que comienzan con un guión bajo seguido inmediatamente por una letra mayúscula
- identificadores que contienen guiones bajos adyacentes (o “guiones bajos dobles”)
- Reservado en el espacio de nombres global:
- identificadores que comienzan con un guión bajo
- Además, todo en el
std
el espacio de nombres está reservado. (Sin embargo, puede agregar especializaciones de plantilla).
Desde el estándar C ++ 2003:
17.4.3.1.2 Nombres globales [lib.global.names]
Ciertos conjuntos de nombres y firmas de funciones siempre están reservados para la implementación:
- Cada nombre que contiene un doble subrayado (
__
) o comienza con un guión bajo seguido de una letra mayúscula (2.11) está reservado a la implementación para cualquier uso.- Cada nombre que comienza con un guión bajo se reserva para la implementación para su uso como nombre en el espacio de nombres global.165
165) Dichos nombres también están reservados en el espacio de nombres.
::std
(17.4.3.1).
Debido a que C ++ se basa en el estándar C (1.1 / 2, C ++ 03) y C99 es una referencia normativa (1.2 / 1, C ++ 03), también se aplican, del estándar C de 1999:
7.1.3 Identificadores reservados
Cada encabezado declara o define todos los identificadores enumerados en su subcláusula asociada y, opcionalmente, declara o define los identificadores enumerados en su subcláusula de instrucciones de biblioteca futura asociada e identificadores que siempre están reservados para cualquier uso o para su uso como identificadores de alcance de archivo.
- Todos los identificadores que comienzan con un guión bajo y una letra mayúscula u otro guión bajo están siempre reservados para cualquier uso.
- Todos los identificadores que comienzan con un guión bajo siempre se reservan para su uso como identificadores con alcance de archivo tanto en el espacio de nombre ordinario como en el de etiqueta.
- Cada nombre de macro en cualquiera de las siguientes subcláusulas (incluidas las instrucciones futuras de la biblioteca) se reserva para su uso como se especifica si se incluye alguno de sus encabezados asociados; a menos que se indique explícitamente lo contrario (ver 7.1.4).
- Todos los identificadores con enlace externo en cualquiera de las siguientes subcláusulas (incluidas las instrucciones futuras de la biblioteca) siempre están reservados para su uso como identificadores con enlace externo.154
- Cada identificador con alcance de archivo enumerado en cualquiera de las siguientes subcláusulas (incluidas las instrucciones futuras de la biblioteca) está reservado para su uso como nombre de macro y como identificador con alcance de archivo en el mismo espacio de nombre si se incluye alguno de sus encabezados asociados.
No se reservan otros identificadores. Si el programa declara o define un identificador en un contexto en el que está reservado (distinto al permitido por 7.1.4), o define un identificador reservado como un nombre de macro, el comportamiento no está definido.
Si el programa elimina (con
#undef
) cualquier macrodefinición de un identificador en el primer grupo enumerado anteriormente, el comportamiento no está definido.154) La lista de identificadores reservados con enlace externo incluye
errno
,math_errhandling
,setjmp
, yva_end
.
Pueden aplicarse otras restricciones. Por ejemplo, el estándar POSIX reserva una gran cantidad de identificadores que es probable que aparezcan en el código normal:
- Nombres que comienzan con mayúscula
E
seguido de un dígito o letra mayúscula:- se puede utilizar para nombres de códigos de error adicionales.
- Nombres que comienzan con
is
oto
seguido de una letra minúscula- se puede utilizar para pruebas de caracteres adicionales y funciones de conversión.
- Nombres que comienzan con
LC_
seguido de una letra mayúscula- se puede utilizar para macros adicionales que especifican atributos de configuración regional.
- Nombres de todas las funciones matemáticas existentes con el sufijo
f
ol
están reservados- para las funciones correspondientes que operan en argumentos dobles flotantes y largos, respectivamente.
- Nombres que comienzan con
SIG
seguidos de una letra mayúscula están reservados- para obtener nombres de señales adicionales.
- Nombres que comienzan con
SIG_
seguidos de una letra mayúscula están reservados- para acciones de señal adicionales.
- Nombres que comienzan con
str
,mem
, owcs
seguidos de una letra minúscula están reservados- para funciones adicionales de cadena y matriz.
- Nombres que comienzan con
PRI
oSCN
seguido de cualquier letra minúscula oX
están reservados- para macros de especificador de formato adicionales
- Nombres que terminan con
_t
están reservados- para obtener nombres de tipos adicionales.
Si bien el uso de estos nombres para sus propios fines en este momento podría no causar un problema, sí plantean la posibilidad de conflictos con versiones futuras de ese estándar.
Personalmente, no comienzo los identificadores con guiones bajos. Nueva adición a mi regla: no use guiones bajos dobles en ningún lugar, lo cual es fácil ya que rara vez uso guiones bajos.
Después de investigar este artículo, ya no termino mis identificadores con _t
ya que está reservado por el estándar POSIX.
La regla sobre cualquier identificador que termine en _t
me sorprendió mucho. Creo que es un estándar POSIX (aún no estoy seguro) en busca de aclaraciones y capítulo y verso oficial. Esto es del manual libtool de GNU, que enumera los nombres reservados.
CesarB proporcionó el siguiente enlace a los símbolos y notas reservados de POSIX 2004 ‘que muchos otros prefijos y sufijos reservados … se pueden encontrar allí’. Los símbolos reservados POSIX 2008 se definen aquí. Las restricciones son algo más matizadas que las anteriores.
Las reglas para evitar la colisión de nombres están tanto en el estándar C ++ (ver el libro Stroustrup) como mencionadas por los gurús de C ++ (Sutter, etc.).
Regla personal
Como no quería ocuparme de casos y quería una regla simple, he diseñado una personal uno que sea simple y correcto:
Al nombrar un símbolo, evitará la colisión con el compilador / SO / bibliotecas estándar si:
- nunca empiece un símbolo con un guión bajo
- nunca nombre un símbolo con dos guiones bajos consecutivos adentro.
Por supuesto, poner su código en un espacio de nombres único también ayuda a evitar colisiones (pero no protege contra macros malignas)
Algunos ejemplos
(Utilizo macros porque son los símbolos de C / C ++ que más contaminan el código, pero podría ser cualquier cosa, desde el nombre de la variable hasta el nombre de la clase)
#define _WRONG
#define __WRONG_AGAIN
#define RIGHT_
#define WRONG__WRONG
#define RIGHT_RIGHT
#define RIGHT_x_RIGHT
Extractos del borrador C ++ 0x
Desde el archivo n3242.pdf (espero que el texto estándar final sea similar):
17.6.3.3.2 Nombres globales [global.names]
Ciertos conjuntos de nombres y firmas de funciones siempre están reservados para la implementación:
– Cada nombre que contenga un subrayado doble _ _ o comience con un subrayado seguido de una letra mayúscula (2.12) está reservado a la implementación para cualquier uso.
– Cada nombre que comienza con un guión bajo se reserva para la implementación para su uso como nombre en el espacio de nombres global.
Pero también:
17.6.3.3.5 Sufijos literales definidos por el usuario [usrlit.suffix]
Los identificadores de sufijos literales que no comienzan con un guión bajo están reservados para una futura estandarización.
Esta última cláusula es confusa, a menos que considere que un nombre que comience con un guión bajo y seguido de una letra minúscula estaría bien si no definido en el espacio de nombres global …
Desde MSDN:
El uso de dos caracteres de subrayado secuenciales (__) al comienzo de un identificador, o un único subrayado inicial seguido de una letra mayúscula, está reservado para las implementaciones de C ++ en todos los ámbitos. Debe evitar el uso de un guión bajo inicial seguido de una letra minúscula para los nombres con alcance de archivo debido a posibles conflictos con los identificadores reservados actuales o futuros.
Esto significa que puede usar un solo guión bajo como prefijo de variable miembro, siempre que esté seguido de una letra minúscula.
Aparentemente, esto se tomó de la sección 17.4.3.1.2 del estándar C ++, pero no puedo encontrar una fuente original para el estándar completo en línea.
Vea también esta pregunta.