EDIT
Short answer: NO!
You can only use contextual keywords like override
as identifiers. But you shouldn't. The standard only allows this for backwards compatibility, which might be removed or deprecated. And also making it to work for every keyword would mean to break many other semantics of the language.
Think about an alternative way to name the enum entries.
END EDIT
NOTE
I tried to make it possible by using the C-preprocessor.
The following code examples are neither good practice nor allowed by the standard. The following code examples should only demonstrate the behavior of the C-preprocessor. Using these techniques could cause problems especially when using library headers, because redefining these keywords can change the semantics of any code.
END NOTE
With some names, it is possible to do this with macros, here are all keywords made useable as normal identifiers without loss of meaning of the keywords itself. At first, storing them into a constant or typedefing the types with valid identifiers like nokw_true
or nokw_bool
. Then defining macros with the keyword-name to refer to the aliases.
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
NOTE
I tested this code and it worked as if the macros were never defined. But there is no guarantee that it behaves the same on every C++ compiler, because it is not the same, keywords are very different from identifiers. And it is not forward compatible with newer C++ standarts, because they could add new syntax using these keywords, which would be invalid with identifiers under the hood.
END NOTE
With other fundamental types like int
or char
it wouldn't be possible anymore to use them like unsigned long int
or signed char
when redeclared with using
/typedef
. The types whar_t
, char16_t
and char32_t
are most of the time declared by a typedef and so not a "real" keyword, but if your compiler implements it directly as a keyword, you can make it useable as an identifier with the using nokw_* = *;
approach.
NOTE Just don't do it! END NOTE
The *_cast
-keywords may also be made as a non-keyword, by defining them in a function:
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
Other keywords cannot be defined, because they are neither a type nor a function-like keyword as the cast-operators. In your case the delete
-keyword cannot exist with the identifier at the same time, because delete has special syntactic meaning. Consider delete ptr
or deleted functions.
But using the definitions above it is possible to implement a tribool
with the keywords true
and false
as an enum. The class
-keyword is important here, because the names may collide with the previously defined names/the use of the identifiers is ambigious.
enum class tribool { true, maybe, false };
Or it could alse be in a namespace:
// 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
};
The enum-entries can be used like tribool::true
.
HOWEVER: Many programmers use CAPITALIZED enum-entry-names. Because there are no capitalized keywords, these will always work...
NOTE
This is no violation against the C++-standard nor the C-standard. This is also why it is often recommended to use CAPITALIZED macronames. Macros are globally visible to all files included after the definition, other entities can and should be nested in namespaces. Otherwise it might lead to name clashes. When you need to define something as a macro, you should prepend some unique text to the macroname like your library/app name as you would name a C++-namespace. This was also called namespaces, before C++ even had namespaces. Look at OpenGL for example, all identifiers are prepended with GL
, this works as good as C++ namespaces, but it does not allow constructs as using ns::the_class
or using namespace
, which however you should never use (globally).
END NOTE
I would go with
enum class EServerAction {
CREATE,
READ,
UPDATE,
DELETE
};
NOTE
When I wrote this, I tried to keep all the semantics of the keywords; but even touching the keywords by redefining them as macros is very bad, because it is forbidden by the standard. You might never know how libraries/standard library implementations/specific system headers use or potentially redefine them.
END NOTE