Is there any way to check preprocessor character type in C / C ++

Parts of my code depend on the value of the preprocessor symbol:

int a() { #if SDK_VERSION >= 3 return 1; #else return 2; #endif } 

The comparison depends on the value of SDK_VERSION. It is expected that in this case there will be an integer or something that compares with the integer. 3. If SDK_VERSION is something that cannot be compared with an integer, a compilation error will occur.

Is there a way to abort compilation if SDK_VERSION does not have the expected type? For example:

 #if type(SDK_VERSION) != int # Does not compile, I know #error "SDK_VERSION must be an integer." #endif 
+7
source share
6 answers

Use the template to create this error:

 template<typename T> struct macro_error; template<> struct macro_error<int> {}; template<typename T> void check(T) { macro_error<T> SDK_VERSION_must_be_int; } int ignored = (check(SDK_VERSION), 0); 

This code generates a compilation error by having the following line in it if SDK_VERSION not int:

 SDK_VERSION_must_be_int 

Watch these demos:

And also pay attention to the error message in the first case. He prints this:

 prog.cpp:9: error: 'SDK_VERSION_must_be_int' has incomplete type prog.cpp:9: warning: unused variable 'SDK_VERSION_must_be_int' 
+11
source

Nope. The reason is that the preprocessor symbol has no type at all.

Preprocessor characters are best understood as slightly larger than a string. A type C system does not actually exist before the compilation stage, which occurs after the preprocessor has already managed.

+4
source

This will not compile if SDK_VERSION is a string (but it will work for float ...):

 int get_SDK_Version() { return SDK_VERSION; } 
+2
source

The preprocessor does not know the types or any language keywords.

0
source

I think you could turn off meta-programming of templates here.

I will try my own magic and send an example if I succeed. My theory is that you can instantiate a class or function template. Defining a default template will result in a compilation error if it does not match the corresponding type. However, template specialization for int would not lead to an error.

This is beyond my experience with template and preprocessing magic, but worth a look. I expect SDK_VERSION not more than a character to replace. SDK_VERSION not of type per-se.

In the best case, I think you can check what type it can convert to, but the concept of the preprocessor, a certain "constant", is very ... brute force, almost hacker. This may be common practice, but it is not at all safe. It’s best to remember that this is just a preprocessor version of find-and-replace.

0
source

In fact, the #if directive treats what is its right as integers.

So, if you want to achieve what you requested, you need to do some arithmetic. For example, run test.c with

 #define VERSION 7 #if VERSION #if VERSION - (VERSION % 10 ) #warning Number out of range (1-9) #else #warning Number in range (1-9) #endif #else #warning Zero or not a number #endif 

Compile with

 gcc -c -o /dev/null test.c 

You will receive a message: "Zero of not number" ... if your VERSION is 0 or does not evaluate (preprocessor) as an integer.

And if VERSION evalutates as an integer, you will get the first or second message according to its value.

This will allow you to do what you were looking for.

#If documentation: http://gcc.gnu.org/onlinedocs/cpp/If.html

Note that an integer can be expressed as: 123 or 0xCC or anything that evaluates to an integer constant after a recursive extension of a macro.

If the number is a floating point, for example: 3.14, it is considered zero.

You cannot just distinguish 0 (integer) from something that is not an integer. There is probably a chance using macro concatenation, but it remains to be explored.

0
source

All Articles