Reputation: 3268
Is there a way that I can force a preprocessor macro in C++ to emit an error? What I would like to do is define a macro UNKNOWN
. I'm writing some code for a robot, and I don't yet know where all of the electronics are being plugged in. I'd like to be able to define the ports in some header file, like
const int MOTOR_PORT = 1;
const int FAN_PORT = 2;
//etc.
However, when I reach a port that I don't yet know, I want to be able to write something like
const int LED_PORT = UNKNOWN;
In debug mode, UNKNOWN
would just be defined to some arbitrary value, like 0. However, when compiling in release mode, I want it to throw an error when UNKNOWN
is used, so that unassigned ports don't end up in the final release. I know I can use the #error
directive to force an error, but can I do something similar in a macro?
I've seen a solution using static_assert
, but I unfortunately can't use C++11 for this platform.
Upvotes: 1
Views: 2371
Reputation: 263647
Since #error
can't result from a macro expansion, you can ensure that the macro expands to something that must be diagnosed, like a syntax error.
For example:
#ifdef RELEASE
#define UNKNOWN @Invalid_use_of_UNKNOWN
#else
#define UNKNOWN 0
#endif
const int MOTOR_PORT = 1;
const int FAN_PORT = 2;
const int LED_PORT = UNKNOWN;
int main(void) {
int x = LED_PORT;
}
The @
character isn't part of C's basic character set, so its appearance outside a comment, character constant, or string literal should always result in an error message. ($
would work, except that accepting $
in identifiers is a common extension. `
would probably also work, but @
stands out better.)
I've defined the macro so it produces a reasonable error message with gcc:
c.c:9:1: error: stray ‘@’ in program
c.c:9:22: error: ‘Invalid_use_of_UNKNOWN’ undeclared here (not in a function)
and with clang:
c.c:9:22: error: expected expression
const int LED_PORT = UNKNOWN;
^
c.c:2:17: note: expanded from:
#define UNKNOWN @Invalid_use_of_UNKNOWN
^
1 error generated.
(There's a _Pragma
operator corresponding to the #pragma
directive. It would be nice if there were an _Error
operator as well, but there isn't.)
Upvotes: 2
Reputation: 4895
The sizeof
operator cannot be applied to an incomplete type, so try this:
// Declared, but not defined anywhere.
struct illegal_use_of_unknown_macro;
#define UNKNOWN (sizeof (illegal_use_of_unknown_macro))
Upvotes: 0
Reputation: 526
Well, this does not produce a complier error message like #error, but would compile in debug and fail in release:
#ifdef _DEBUG
# define UNKNOWN 1
#else
# define UNKNOWN
#endif
const int port1 = UNKNOWN; // fail in release
Upvotes: 1
Reputation: 11502
You could make a division by zero which will throw a compiler error:
#define UNKNOWN 0/0
Upvotes: 0