c++ - tipos - reglas para crear identificadores
¿Hay una manera de usar una palabra clave como identificador en una enumeración? (5)
No he podido encontrar si hay una manera de usar una palabra clave en una definición de enumeración, como:
enum class EServerAction
{
create,
read,
update,
delete
};
En C # puedo usar el carácter @ para hacer que el compilador lo vea como un identificador. ¿Hay alguna manera de hacer esto en C ++ (Visual Studio 2015)?
Con algunos nombres, es posible hacer esto con macros, aquí están todas las palabras clave que se pueden utilizar como identificadores normales sin perder el significado de las palabras clave en sí. Al principio, almacenándolos en una constante o tipografiando los tipos con identificadores válidos como nokw_true
o nokw_bool
. Luego, definir macros con el nombre de palabra clave para referirse a los alias.
constexpr static nullptr_t nokw_nullptr = nullptr;
constexpr static bool nokw_true = true;
constexpr static bool nokw_false = false;
using nokw_bool = bool;
using nokw_void = void; // suprising: this can also be used for empty parameter list
#define nullptr nokw_nullptr
#define true nokw_true
#define false nokw_false
#define bool nokw_bool
#define void nokw_void
Con otros tipos fundamentales, como int
o char
, ya no sería posible usarlos como unsigned long int
o signed char
cuando se redeclariza con using
/ typedef
. Los tipos whar_t
, char16_t
y char32_t
se char32_t
mayoría del tiempo mediante typedef y, por lo tanto, no son palabras clave "reales", pero si el compilador lo implementa directamente como palabra clave, puede hacer que sea utilizable como identificador con el using nokw_* = *;
enfoque.
Las *_cast
clave *_cast
también se pueden crear como una palabra clave, definiéndolas en una función:
template<typename N, typename O>
N nokw_reinterpret_cast(O&& old) { return reinterpret_cast<N>(old); };
#define reinterpret_cast nokw_reinterpret_cast
// other cast-operators follow
Otras palabras clave no se pueden definir, ya que no son un tipo ni una palabra clave similar a una función como los operadores de conversión. En su caso, la palabra clave delete
no puede existir con el identificador al mismo tiempo, porque delete tiene un significado sintáctico especial. Considere delete ptr
o funciones eliminadas.
Pero utilizando las definiciones anteriores, es posible implementar un tribool
con las palabras clave true
y false
como una enumeración. La palabra clave de class
es importante aquí, porque los nombres pueden chocar con los nombres definidos previamente / el uso de los identificadores es ambiguo.
enum class tribool { true, maybe, false };
O también podría estar en un espacio de nombres:
// maybe writing an API for a Visual Basic Application
namespace vb_constants {
constexpr int true = -1; // in VB True is -1
constexpr int false = 0;
// in this namespace the real true and the real false can
// be accessed through ::true and ::false
};
Las entradas de enumeración se pueden utilizar como tribool::true
.
SIN EMBARGO: Muchos programadores usan nombres de entrada enumeración CAPITALIZADOS. Como no hay palabras clave en mayúscula, estas siempre funcionarán ...
Yo iria con
enum class EServerAction {
CREATE,
READ,
UPDATE,
DELETE
};
En C ++, las palabras clave no se pueden usar como identificadores como pueden en C #.
Es posible hacer esto usando macros:
#define delete _delete
enum class EServerAction
{
create,
read,
update,
delete
};
Esta práctica generalmente se desaconseja porque ahora no puede usar delete
en otras partes del archivo. Pero es útil en algunas situaciones como cuando compilamos un programa de C que tiene identificadores nombrados como palabras clave de C ++ (como delete
) usando un compilador de C ++.
Esto también causará confusión en el depurador porque los identificadores de los símbolos no son los mismos identificadores que están en el código fuente.
No, no pueden ser utilizados.
Desde MSDN
Las palabras clave son identificadores reservados predefinidos que tienen significados especiales. No se pueden utilizar como identificadores en su programa.
La rule para el identificador dice:
Se puede usar un identificador para nombrar objetos, referencias, funciones, enumeradores, tipos, miembros de clase, espacios de nombres, plantillas, especializaciones de plantillas, paquetes de parámetros, etiquetas de goto y otras entidades, con las siguientes excepciones:
- los identificadores que son palabras clave no pueden utilizarse para otros fines;
- Los identificadores con un subrayado doble en cualquier lugar están reservados;
- los identificadores que comienzan con un guión bajo seguido de una letra mayúscula están reservados;
- los identificadores que comienzan con un guión bajo se reservan en el espacio de nombres global.
Según 2.12 [lex.key] en el estándar C ++ 14, ciertos identificadores nunca deben usarse como identificadores:
Los identificadores que se muestran en la Tabla 4 se reservan para su uso como palabras clave (es decir, se tratan incondicionalmente como palabras clave en la fase 7), excepto en un token de atributo (7.6.1) [Nota: la palabra clave de exportación no se usa, pero se reserva para uso futuro . - nota final]:
Tabla 4 - Palabras clave
alignas continue friend register true alignof decltype goto reinterpret_cast try asm default if return typedef auto delete inline short typeid bool do int signed typename break double long sizeof union case dynamic_cast mutable static unsigned catch else namespace static_assert using char enum new static_cast virtual char16_t explicit noexcept struct void char32_t export nullptr switch volatile class extern operator template wchar_t const false private this while constexpr float protected thread_local const_cast for public throw
Además, no se utilizarán algunos identificadores:
Además, las representaciones alternativas que se muestran en la Tabla 5 para ciertos operadores y puntuadores (2.6) están reservadas y no se utilizarán de otro modo:
Tabla 5 - Representaciones alternativas
and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq
Aún más, según el identificador 2.11 [lex.name], algunos son de uso ilegal , pero el compilador no está obligado a decirle:
algunos identificadores están reservados para su uso por implementaciones de C ++ y bibliotecas estándar (17.6.4.3.2) y no se usarán de otra manera; no se requiere diagnóstico
- Cada nombre que contiene un doble guión bajo _ _ o comienza con un guión bajo 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 está reservado a la implementación para su uso como un nombre en el espacio de nombres global.