11

I would like to use the following preprocessor defines:

[3rd party header (cannot modify)]

#define SWCI_VERSION_MAJOR              (unsigned char) 4
#define SWCI_VERSION_MINOR              (unsigned char) 16

When they are compared in this way:

[my implementation]

#if SWCI_VERSION_MAJOR >= 4 && SWCI_VERSION_MINOR >= 16

Then I get:

fatal error C1017: invalid integer constant expression

I have noticed that if I define them without (unsigned char) the directive will be accepted, but I have no access to the defines so I would like to workaround the issue if possible.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
j4nSolo
  • 342
  • 1
  • 14
  • 1
    Possible duplicate of [what does the compiler error "missing binary operator before token" mean?](http://stackoverflow.com/questions/21338385/what-does-the-compiler-error-missing-binary-operator-before-token-mean) – BoBTFish Feb 24 '16 at 13:59
  • 3
    Note that the error message is different from http://stackoverflow.com/q/21338385/1171191 because it's a different compiler, but the error is the same: you can't cast in an `#if`, because it doesn't happen in the preprocessor, as AShelly's answer explains. – BoBTFish Feb 24 '16 at 14:00
  • @j4nSolo if you compare it the way you mentioned, what is preventing you from defining the MACROs without (unsigned char) ? – Sam Daniel Feb 24 '16 at 14:06
  • @SamDaniel I just edited the question so that it gets clear that I cannot redefine the MACROs – j4nSolo Feb 24 '16 at 14:19
  • @j4nSolo is it an open-source third party header that you could give us a link to? – villapx Feb 24 '16 at 14:34
  • 1
    Strongly related (conflicted about whether to insta-close as dupe): [Remove cast from constant in preprocessor](http://stackoverflow.com/questions/19406246/remove-cast-from-constant-in-preprocessor) – Cody Gray - on strike Feb 24 '16 at 14:34
  • @villapx Unfortunately not. – j4nSolo Feb 24 '16 at 14:34

4 Answers4

14

You can get this to work with a little preprocessor magic. Due to the way the preprocessor applies macros, you can sometimes do some modifications by using multiple macro levels. Boost.Preprocessor exploits this behavior. This code takes advantage of the fact that (unsigned char) looks like can be made into a macro invocation by prepending the macro name X which evaluates to nothing, leaving only the trailing number.

#define SWCI_VERSION_MAJOR              (unsigned char) 4
#define SWCI_VERSION_MINOR              (unsigned char) 16

#define X(unused)
#define APPLY(x) x

#define MAJOR (APPLY(X SWCI_VERSION_MAJOR))
#define MINOR (APPLY(X SWCI_VERSION_MINOR))

#if MAJOR >= 4 && MINOR >= 16
#error "Version is greater or equal to 4.16"
#endif

See https://goo.gl/GOsLDL for an example of the #if evaluating true and printing the #error message I added.

Kurt Stutsman
  • 3,994
  • 17
  • 23
2

Maybe using a constexpr function will do the trick? Something like

constexpr bool version_supported(const char major, const char minor)
{
    return major >= 4 && minor >= 16;
}
constexpr VERSION_SUPPORTED = version_supported(SWCI_VERSION_MAJOR, SWCI_VERSION_MINOR);
Vorac
  • 8,726
  • 11
  • 58
  • 101
0

The problem is that you cannot use these macros as proper numbers. Depending on what you want to do inside the if block, you can consider making it a non-preprocessed statement:

// Note the next line does not start with a #
if((unsigned int)SWCI_VERSION_MAJOR >= 4 && (unsigned int)SWCI_VERSION_MINOR >= 16) 
{
  // ...
}

but that only works of course if you are using it inside a function and the contents of the if block are not preprocessor statements like defines.

CompuChip
  • 9,143
  • 4
  • 24
  • 48
-2

Just consider the following

#define SWCI_VERSION_MAJOR              (unsigned char) 4
#define SWCI_VERSION_MINOR              (unsigned char) 16

When used in the following expression:

#if SWCI_VERSION_MAJOR >= 4 && SWCI_VERSION_MINOR >= 16

This will be transformed (by preprocessor) to the following #if (unsigned char) 4 > 4

The issue is that this expression (unsigned char) 4 > 4 seems to be wrong.

If you cannot change 3rd-party header files, you may try to use

#undef SWCI_VERSION_MAJOR

But this heavily depends on #include order

rezdm
  • 165
  • 1
  • 11
  • 4
    If I undef the defines I cannot use their values. That is the opposite of what I want to achieve. – j4nSolo Feb 24 '16 at 14:19
  • You can undef and then define it correctly (with brackets). Here is what I mean: include1.h ` #define SWCI_VERSION_MAJOR (unsigned char) 4` ` #define SWCI_VERSION_MINOR (unsigned char) 16` includeA.h ` #if SWCI_VERSION_MAJOR >= 4 && SWCI_VERSION_MINOR >= 16` ` do_something_if_version_is_as_expected() ` #endif` your.cpp ` #include "include1.h"` ` #undef SWCI_VERSION_MAJOR` ` #undef SWCI_VERSION_MINOR` ` #define SWCI_VERSION_MAJOR ((unsigned char) 4)` ` #define SWCI_VERSION_MINOR ((unsigned char) 16)` your code – rezdm Feb 24 '16 at 14:20
  • ... sorry formatting went wrong. The idea is to include .h, where this define is defined, then undef it in your .c/.cpp and redefine correctly. – rezdm Feb 24 '16 at 14:28