I wish to add some conditional directive in my code to control different build, for example:
#if VERSION > 100
/* Compiling here */
#endif
The problem is that 'VERSION' is in other's code where I can't change. It was defined as a string:
#define VERSION "101"
I'm wondering if there's some sort of macro or directive which converts the string to number so I can simply do
#if STRING_TO_NUMBER(VERSION) > 100
/* Compiling here */
#endif
Is that possible please?
PS. It seems my description is not quite clear. The main purpose of this requirement is to control the version branch. For example, in old version, pre-version 100, this program would like old_function(). After this version, all functions have been migrated to new_function. So I need to write codes like that:
#if VERSION >= 100
old_function();
#else
new_function();
#endif
#if VERSION >= 100
int old_function()
{
...
}
#else
int new_function()
{
...
}
#endif
You can see that only one of the function will be compiled. Therefore the condition must be decided in preprocessing stage, not in the runtime.
The tricky part is, the VERSION had been defined as a string, which brought this question.
If you need to interact with the pre-processor to set other #defines
or conditionally #include
different headers. Until you can get VERSION to be "fixed" to be an integer...
The only thing that I can think of for you to do is to create a tiny header file defining PROPER_VERSION and include it by naming each file as the version number. So here you would create:
100:
#define PROPER_VERSION 100
101:
#define PROPER_VERSION 101
102:
#define PROPER_VERSION 102
and then you would need to add the following:
#include VERSION
And then use PROPER_VERSION
as you need
#if PROPER_VERSION > 100
...
Its not elegant, but I cannot see anything else you can do. You can auto-generate the VERSION file.
As long as you don't need to make declarations or preprocessor defines conditional on VERSION
, and as long as you are confident that the VERSION
string will just be an integer with no leading zeros, (both of which might be too much to ask for), you might be able to do this at compile time if your compiler has a reasonably effective constant expression evaluator.
For example, gcc 4.8 will optimize away the following if
test, leaving only the appropriate arm:
if (strlen(VERSION) > 3 || (strlen(VERSION) == 3 && strcmp(VERSION, "100") > 0)) {
// code if VERSION is at least "101"
} else {
// code if VERSION is "100" or less
}
The fact that only one of the branches of the if
statement survives the compilation is easily demonstrated by inserting a call to an undefined function in the non-used branch. With gcc (and clang), and with optimization enabled, no linker error is produced:
#include <stdio.h>
#include <string.h>
#define VERSION "101"
// This function is not available for linking
int unknown_function();
// This one is in standard library
int rand();
int main(void) {
int x;
if (strlen(VERSION) > 3 || (strlen(VERSION) == 3 && strcmp(VERSION, "100") > 0)) {
// code if VERSION is at least "101"
x = rand();
} else {
// code if VERSION is "100" or less
x = unknown_function();
}
printf("%d\n", x);
return 0;
}
(See it at http://ideone.com/nGLGTH)
In C++11, there is an even more clearly compile-time version. You can create a constexpr
version of atoi
. Combined with what some might call an abuse of templates, that allows for conditional declarations:
constexpr int const_atoi(const char* num, int accum=0) {
return *num ? const_atoi(num+1, accum*10 + (*num - '0')) : accum;
}
template<bool V_GT_100> struct MoreOrLess_Impl;
template<> struct MoreOrLess_Impl<false> {
// Old prototype
void doit(double x) {...}
};
template<> struct MoreOrLess_Impl<true> {
// New prototype
void doit(long double x) {...}
};
using MoreOrLess = MoreOrLess_Impl<(const_atoi(VERSION) > 100)>;
// ...
// ... MoreOrLess::doit(x) ...
(Silly example at http://ideone.com/H1sdNg)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With