Print fully evaluated result of #define during compilation using #pragma message() - c++

I have a quick question regarding printing the evaluated values of #defines using #pragma message. I'm using msvc++ in Visual Studio 2008.
Below is a simplified example:
#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
#define WIDTH 10
#define HEIGHT 10
#define AREA (WIDTH * HEIGHT)
#pragma message("Area is: " __STR1__(AREA))
Now when I compile I get the following output:
>Area is: (10 * 10)
This is not exactly what I want. Is there any way to print out the evaluation of a #define expression so that I get:
>Area is: 100
during compilation. Perhaps this is not possible. Eventually I want to be able to cause a compiler error if the evaluated value is too large. i.e.
#if(AREA > 1000)
#pragma message(__ERROR__)
#endif
Some of my #defines use sizeof() which I believe causes issues in itself when evaluating conditionals - but that's a problem for the future!
I looked at the following post How do I show the value of a #define at compile time in gcc which is fine as long as the #define is defined as a value, and not a concatenation of other #defines.

The preprocessor won't do math for you, it can only substitute tokens and expand macros in a textual way.
If you want to calculate that value during compilation you should go for constexpr (http://en.cppreference.com/w/cpp/language/constexpr, more precisely this will hint the compiler to calculate it at compile-time)
#include <iostream>
#define WIDTH 10
#define HEIGHT 10
template<int a, int b>
constexpr int getArea() {
static_assert(a*b < 1000, "Area is too big");
return a*b;
}
const int area = getArea<WIDTH, HEIGHT>();
int main(void) {
std::cout << area;
}
Example
static_assert will do the check for the area if it is too large.

The precompiler can do limited math in #if statements. This may be sufficient for your needs:
#define WIDTH 10
#define HEIGHT 10
#define AREA (WIDTH * HEIGHT)
#if AREA > 1000
#error Oh bad, oh bad, oh bad
#endif
For more complex mathematics I would second what Marco A. said but you don't need that in a template or anything.
You can just put it up with all your #defines, for example:
#define WIDTH 10
#define HEIGHT 10
#define AREA (WIDTH * HEIGHT)
#define __ERROR__ "Oh bad, oh bad, oh bad"
static_assert(AREA < 1000, __ERROR__);
Or even simpler: static_assert(WIDTH * HEIGHT < 1000, "Oh bad, oh bad, oh bad");

Related

redefining a macro not working as expected

I am in C++ defining blocks that go in a special area of memory. I want to define a block, then define the address of the next block in a variable that gets redefined for each block.
#include <iostream>
using namespace std;
#define BASE_ADDRESS 0X1000
// type a gets 100 bytes
#define TYPE_A BASE_ADDRESS
#define NEXT_FREE_BLOCK (BASE_ADDRESS + 100)
// type b gets 200 bytes, starting at the next free address
#define TYPE_B NEXT_FREE_BLOCK
#undef NEXT_FREE_BLOCK
#define NEXT_FREE_BLOCK (TYPE_B + 200)
// ---end of RWW memory map---
int main()
{
cout<<"Hello free block " << NEXT_FREE_BLOCK << endl;
return 0;
}
Example code that I've looked up looks like this. But when I try to compile this, I get "compilation failed due to the following errors":
main.cpp:12:16: error: ‘NEXT_FREE_BLOCK’ was not declared in this scope
#define TYPE_B NEXT_FREE_BLOCK
^
main.cpp:14:26: note: in expansion of macro ‘TYPE_B’
#define NEXT_FREE_BLOCK (TYPE_B + 200)
^~~~~~
main.cpp:20:34: note: in expansion of macro ‘NEXT_FREE_BLOCK’
cout<<"Hello free block " << NEXT_FREE_BLOCK << endl;
^~~~~~~~~~~~~~~
If I comment out the 'type b' lines, it runs as expected. If I comment out the #undef line, it tells me I've redefined the macro. I would like to redefine the macro without getting an error or warning; is there a way to do that?
Lets take a look at this example:
#define MYMACRO 0 //MYMACRO = 0
#define ANOTHERMACRO MYMACRO //ANOTHERMACRO = MYMACRO = 0
int main() {
return ANOTHERMACRO;
}
All good right?
But if we do this:
#define MYRECURSIVEMACRO 0 //MYRECURSIVEMACRO = 0
#define MYMACRO MYRECURSIVEMACRO //MYMACRO = MYRECURSIVEMACRO
#undef MYRECURSIVEMACRO // MYRECURSIVEMACRO does not exist
#define MYRECURSIVEMACRO (MYMACRO+10) //What was MYMACRO again? It was MYRECURSIVEMACRO, but now we are setting MYRECURSIVEMACRO, which right now is being defined, to itself plus 10, and now I am 100% confused
#define ANOTHERMACRO MYRECURSIVEMACRO //Now what?
int main() {
return ANOTHERMACRO;
}
We get this:
1>C:\dev\Stack Overflow\Source.cpp(520,9): error C2065: 'MYMACRO': undeclared identifier
(At least for MSVC++)
Now if we look at this:
#define BASE_ADDRESS 0X1000 //BASE_ADDRESS = 0x1000
// type a gets 100 bytes
#define TYPE_A BASE_ADDRESS //TYPE_A = BASE_ADDRESS = 0x1000
#define NEXT_FREE_BLOCK (BASE_ADDRESS + 100) //NEXT_FREE_BLOCK = 0x1000 + 100
// type b gets 200 bytes, starting at the next free address
#define TYPE_B NEXT_FREE_BLOCK //TYPE_B = NEXT_FREE_BLOCK
#undef NEXT_FREE_BLOCK //NEXT_FREE_BLOCK is gone
#define NEXT_FREE_BLOCK (TYPE_B + 200) //Now what? Same problem as before!
// ---end of RWW memory map---
This is why it isn't working.

How to get a boolean indicating if a macro is defined or not?

My code is configurable with define macros. To get the value in the code, I'm doing this:
#ifdef CONFIG_X
static constexpr bool x = true;
#else
static constexpr bool x = false;
#endif
But this is quickly becoming very ugly in the code with several configuration variables...
Another solution I found is simply to cut the code in two:
#ifdef CONFIG_X
#define CONFIG_X_BOOL true
#else
#define CONFIG_X_BOOL false
#endif
static constexpr bool x = CONFIG_X_BOOL;
This is a bit better, but not really nice either.
Is there a nice way to have a boolean or a 1 or 0 if a macro is defined ?
This IS possible, but only in the limited case where you are looking for empty defines (as is often the case with compilation flags) or where you know the range of ways a flag will be defined, such as with a 0 or 1.
Here is working code:
#include <iostream>
// Define two genetic macros
#define SECOND_ARG(A,B,...) B
#define CONCAT2(A,B) A ## B
// If a macro is detected, add an arg, so the second one will be 1.
#define DETECT_EXIST_TRUE ~,1
// DETECT_EXIST merely concats a converted macro to the end of DETECT_EXIST_TRUE.
// If empty, DETECT_EXIST_TRUE converts fine. If not 0 remains second argument.
#define DETECT_EXIST(X) DETECT_EXIST_IMPL(CONCAT2(DETECT_EXIST_TRUE,X), 0, ~)
#define DETECT_EXIST_IMPL(...) SECOND_ARG(__VA_ARGS__)
// We will create MY_DEFINE, but not MY_DEFINE2
#define MY_DEFINE
int main()
{
// We can now use DETECT_EXIST to detect defines.
std::cout << "MY_DEFINE = " << DETECT_EXIST(MY_DEFINE) << std::endl;
std::cout << "MY_DEFINE2 = " << DETECT_EXIST(MY_DEFINE2) << std::endl;
}
This code will produce the output:
MY_DEFINE = 1
MY_DEFINE2 = 0
Since the first one does exist and the second doesn't.
If the macro is set to a value such as 1, you just need to have an alternate version of DETECT_EXIST_TRUE to handle it, with the macro value pasted on the end. For example:
#define DETECT_EXIST_TRUE1 ~,1
Then if you have:
#define MY_DEFINE1 1
Code like this will also work correctly in main:
std::cout << "MY_DEFINE1 = " << DETECT_EXIST(MY_DEFINE1) << std::endl;
#ifndef CONFIG_X
#error "Written for config x"
#endif
// True for config x, hack this about for other configurations
static bool x = 1;
Now it breaks if config is not x. Generally that's better than trying to second-guess what an unnamed configuration which is not X will require.

C++ Macro Arguments w/ Token Concatenation?

I have a bunch of labeled servos, each one has its own calibrated min, mid and max pulse-width value.
// repository of calibrated servo pulse width values:
#define SERVO_0x01_MIN 165
#define SERVO_0x01_MID 347
#define SERVO_0x01_MAX 550
#define SERVO_0x02_MIN 165
#define SERVO_0x02_MID 347
#define SERVO_0x02_MAX 550
...
To simplify maintenance of the code, swapping a servo should only require changing a single macro definition value.
// maps certain positions on robot to the servo that is installed there
#define JOINT_0 0x02
#define JOINT_1 0x05
#define JOINT_2 0x0A
...
// function-like macros to resolve values from mapping
#define GET_MIN(servo) SERVO_##servo##_MIN
#define GET_MID(servo) SERVO_##servo##_MID
#define GET_MAX(servo) SERVO_##servo##_MAX
The problem I'm having is that calling a function-like macro with an argument that itself is a macro does not resolve to its terminal value:
// main
int main(void) {
// this works
int max_0x01 = GET_MAX(0x01); // int max_0x01 = 550;
// this doesn't
int max_joint_0 = GET_MAX(JOINT_0); // int max_joint_0 = SERVO_JOINT_0_MAX;
}
What can I do to make GET_MAX(JOINT_0) turn into 550 ?
#define GET_MAX(servo) GET_MAX2(servo)
#define GET_MAX2(servo) SERVO_##servo##_MAX
The preprocessor will perform expansion (textual replacement) upon a variadic macro until it can expand no further. So passing in JOINT_0, such as GET_MAX(JOINT_0) will expand to
GET_MAX2(0x02)
This gets further expanded to
SERVO_0x02_MAX
And finally replaced with the #define value 550

Why does the C preprocessor consider enum values as equal?

Why does the std::cout line in the following code run even though A and B are different?
#include <iostream>
enum T { A = 1, B = 2 };
// #define A 1
// #define B 2
int main() {
#if (A == B)
std::cout << A << B;
#endif
}
If I use #define instead (as commented out), I get no output as I expect.
Reason for the question:
I want to have a mode selector for some test code in which I can easily change modes by commenting/uncommenting lines on top:
enum T { MODE_RGB = 1, MODE_GREY = 2, MODE_CMYK = 3 };
// #define MODE MODE_RGB
#define MODE MODE_GREY
// #define MODE MODE_CMYK
int main() {
#if (MODE == MODE_RGB)
// do RGB stuff
#elif (MODE == MODE_GREY)
// do greyscale stuff
#else
// do CMYK stuff
#endif
// some common code
some_function(arg1, arg2,
#if (MODE == MODE_RGB)
// RGB calculation for arg3,
#elif (MODE == MODE_GREY)
// greyscale calculation for arg3,
#else
// CMYK calculation for arg3,
#endif
arg4, arg5);
}
I know I can use numeric values e.g.
#define MODE 1 // RGB
...
#if (MODE == 1) // RGB
but it makes the code less readable.
Is there an elegant solution for this?
There are no macros called A or B, so on your #if line, A and B get replaced by 0, so you actually have:
enum T { A = 1, B = 2 };
int main() {
#if (0 == 0)
std::cout << A << B;
#endif
}
The preprocessor runs before the compiler knows anything about your enum. The preprocessor only knows about macros (#define).
This is because the preprocessor works before compile time.
As the enum definitions occur at compile time, A and B will both be defined as empty (pp-number 0) - and thus equal - at pre-processing time, and thus the output statement is included in the compiled code.
When you use #define they are defined differently at pre-processing time and thus the statement evaluates to false.
In relation to your comment about what you want to do, you don't need to use pre-processor #if to do this. You can just use the standard if as both MODE and MODE_GREY (or MODE_RGB or MODE_CMYK) are all still defined:
#include <iostream>
enum T { MODE_RGB = 1, MODE_GREY = 2, MODE_CMYK = 3 };
#define MODE MODE_GREY
int main()
{
if( MODE == MODE_GREY )
std::cout << "Grey mode" << std::endl;
else if( MODE == MODE_RGB )
std::cout << "RGB mode" << std::endl;
else if( MODE == MODE_CMYK )
std::cout << "CMYK mode" << std::endl;
return 0;
}
The other option using only the pre-processor is to do this as #TripeHound correctly answered below.
Identifiers that are not defined macros are interpreted as value 0 in conditional preprocessor directives. Therefore, since you hadn't defined macros A and B, they are both considered 0 and two 0 are equal to each other.
The reason why undefined (to the pre-processor) identifiers are considered 0 is because it allows using undefined macros in the conditional without using #ifdef.
As the other answers said, the C preprocessor doesn't see enums. It expects, and can only understand, macros.
Per the C99 standard, §6.10.1 (Conditional inclusion):
After all replacements due to macro expansion and the defined unary operator have been performed, all remaining identifiers are replaced with the pp-number 0
In other words, in an #if or #elif directive, any macros that cannot be expanded, because they don't exist/are undefined, will behave exactly as if they'd been defined as 0, and therefore will always be equal to each other.
You can catch likely unintended behavior like this in GCC/clang with the warning option -Wundef (you'll probably want to make it fatal with -Werror=undef).
The preprocessor runs before the compiler, which means that the preprocessor doesn't know anything about symbols defined by the compiler and therefore it can't act depending on them.
Other answers explain why what you're trying doesn't work; for an alternative, I'd probably go with:
#define RGB 1
#define GREY 2
#define CMYK 3
#define MODE RGB
#if MODE == RGB
//RGB-mode code
#elif MODE == GREY
//Greyscale code
#elif MODE == CMYK
//CMYK code
#else
# error Undefined MODE
#endif
You might want prefixes on the RGB/GREY/CMYK if there's a danger of clashes with "real" source code.
The posts have explained why, but a possible solution for you that keeps readability might be like this
#define MODE_RGB
int main()
{
#ifdef MODE_RGB
std::cout << "RGB mode" << std::endl;
#elif defined MODE_GREY
std::cout << "Grey mode" << std::endl;
#elif defined MODE_CMYK
std::cout << "CMYK mode" << std::endl;
#endif
}
You just then need to change the macro at the top, to only the macro you are interested in is defined. You could also include a check to make sure that one and only one is defined and if not then and do #error "You must define MODE_RGB, MODE_GREY or MODE_CMYK

How much one can do with (higher order) macros?

Is it "safe" to give macros names as arguments to other macros to simulate higher order functions?
I.e. where should I look to not shoot myself in the foot?
Here are some snippets:
#define foreach_even(ii, instr) for(int ii = 0; ii < 100; ii += 2) { instr; }
#define foreach_odd(ii, instr) for(int ii = 1; ii < 100; ii += 2) { instr; }
#define sum(foreach_loop, accu) \
foreach_loop(ii, {accu += ii});
int acc = 0;
sum(foreach_even, acc);
sum(foreach_odd, acc);
What about partial application, can I do that? :
#define foreach(ii, start, end, step, instr) \
for(int ii = start; ii < end; ii += step) { instr; }
#define foreach_even(ii, instr) foreach(ii, 0, 100, instr)
#define foreach_odd(ii, instr) foreach(ii, 1, 100, instr)
#define sum(foreach_loop, accu) \
foreach_loop(ii, {accu += ii});
int acc = 0;
sum(foreach_even, acc);
sum(foreach_odd, acc);
And can I define a macro inside a macro?
#define apply_first(new_macro, macro, arg) #define new_macro(x) macro(arg,x)
If you're into using preprocessor as much as possible, you may want to try boost.preprocessor.
But be aware that it is not safe to do so. Commas, for instance, cause a great number of problems when using preprocessors. Don't forget that preprocessors do not understand (or even try to understand) any of the code they are generating.
My basic advice is "don't do it", or "do it as cautiously as possible".
I've implemented a rotten little unit testing framework entirely in c-preprocessor. Several dozen macro, lots of macro is an argument to another macro type stuff.
This kind of thing is not "safe" in a best-practices sense of the word. There are subtle and very powerful ways to shoot yourself in the foot. The unit testing project is a toy that got out of hand.
Don't know if you can nest macro definitions. I doubt it, but I'll go try...gcc doesn't like it, and responds with
nested_macro.cc:8: error: stray '#' in program
nested_macro.cc:3: error: expected constructor, destructor, or type conversion before '(' token
nested_macro.cc:3: error: expected declaration before '}' token
Self plug: If you're interested the unit testing framework can be found at https://sourceforge.net/projects/dut/