Is it legal to redefine a C++ keyword?
17.4.3.1.1 Macro names [lib.macro.names]
1 Each name defined as a macro in a header is reserved to the implementation for any use if the translation unit includes the header.164)
2 A translation unit that includes a header shall not contain any macros that define names declared or defined in that header. Nor shall such a translation unit define macros for names lexically identical to keywords.
By the way, new
is an operator and it can be overloaded (replaced) by the user by providing its own version.
C++ preprocessor #define-ing a keyword. Is it standards conforming?
In C++, the closest thing to forbidding #define
ing a keyword is §17.4.3.1.1/2, which only disallows it in a translation unit that includes a standard library header:
A translation unit that includes a header shall not contain any macros that define names declared or defined in that header. Nor shall such a translation unit define macros for names lexically identical to keywords.
The second sentence of that paragraph has been changed in C++0x to outright forbid #define
ing a keyword (C++0x FCD §17.6.3.3.1):
A translation unit shall not #define or #undef names lexically identical to keywords.
Edit: As pointed out by Ken Bloom in comments to his answer, the rules have not changed in C++0x; the text has just been rearranged to confuse people like me. :-)
Can I redefine a C++ macro then define it back?
As greyfade pointed out, your ___T___
trick doesn't work because the preprocessor is a pretty simple creature. An alternative approach is to use pragma directives:
// juice includes here
#pragma push_macro("T")
#undef T
// include boost headers here
#pragma pop_macro("T")
That should work in MSVC++ and GCC has added support for pop_macro
and push_macro
for compatibility with it. Technically it is implementation-dependent though, but I don't think there's a standard way of temporarily suppressing the definition.
Redefinition allowed in C but not in C++?
Tentative definition is allowed in C but not in C++.
A tentative definition is any external data declaration that has no storage class specifier and no initializer.
C99 6.9.2/2
A declaration of an identifier for an object that has file scope without an initializer, and
without a storage-class specifier or with the storage-class specifier static, constitutes a
tentative definition. If a translation unit contains one or more tentative definitions for an
identifier, and the translation unit contains no external definition for that identifier, then
the behavior is exactly as if the translation unit contains a file scope declaration of that
identifier, with the composite type as of the end of the translation unit, with an initializer
equal to 0.
So int i
is a tentative definition. The C compiler will combine all of the tentative definitions into a single definition of i
.
In C++ your code is ill-formed due to the One Definition Rule (Section 3.2/1 ISO C++)
No translation unit shall contain more than one definition of any variable, function, class type, enumeration type or template.
// but if I write
int i = 5;
again I get error in C also
Because in that case it no longer remains a tentative definition because of the initializer (5).
Just for the sake of information
J.5.11 Multiple external definitions
There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).
Also check out this excellent post on external variables.
Can I mimic a C header that redefines bool in C++?
You can hack it!
The library, call it fooLib
, thinks it's using some type bool
which it has the prerogative to define. To the library, bool
is just an identifier.
So, you can just force it to use another identifier instead:
#define bool fooLib_bool
#include "fooLib.h"
#undef bool
#undef true
#undef false
Now the compiler sees the offending line transformed to this:
typedef int fooLib_bool;
You're stuck with the interface using type fooLib_bool = int
instead of a real bool
, but that's impossible to work around, as the code might in fact rely on the properties of int
, and library binary would have been compiled with such an assumption baked in.
Related Topics
Outputting Date and Time in C++ Using Std::Chrono
How to Remove All the Occurrences of a Char in C++ String
Is There a Range Class in C++11 for Use with Range Based for Loops
Why Should I Use the "Using" Keyword to Access My Base Class Method
C++ Exception:Throwing Std::String
Std::Fstream Buffering VS Manual Buffering (Why 10X Gain with Manual Buffering)
What Are the Signs of Crosses Initialization
Simple Way to Unzip a .Zip File Using Zlib
How to Emit Cross-Thread Signal in Qt
When Is It Necessary to Use the Flag -Stdlib=Libstdc++
Why Isn't the [] Operator Const for Stl Maps
Structure of Arrays VS Array of Structures
Multiple Definition of Template Specialization When Using Different Objects
C++ Function Pointer (Class Member) to Non-Static Member Function