Juha Nieminen <nos...@thanks.invalid> writes:
> For a project I'm developing, I would want to conditionally compile
> something depending on whether unsigned long is (at least) 64-bit
> or not. And this has to be done in a manner that allows the code
> to be compiled with a C++98 compiler. 100% standard C++ compliance
> as well, obviously.
Here is a way using a rather remarkable macro definition:
#if defined __cplusplus
#include <climits>
#else
#include <limits.h>
#endif
#define MASK_WIDTH( m ) ( 0U + (unsigned)+( \
(m) /((m)%32767 +1) /32767 %32767 *15 \
+ (m) %32767 /((m)%31 +1) /31 %31 *5 \
+ 4 - 12 / ((m)%31 + 3) \
))
#if MASK_WIDTH( ULONG_MAX ) < 64
/* ... unsigned long less than 64 bits ... */
#else
/* ... unsigned long at least 64 bits ... */
#endif
Just to be sure I ran tests with C90, C99, C11, C++98, C++03,
C++11, and C++14. The results were as desired in every case.
Don't be thrown off by what appears to be a cast in the macro
definition. It has no effect when the macro is used in
preprocessor tests, and causes the value of a call to be of type
'unsigned' if and when the macro is used in regular code. It
does not interfere with using the value a MASK_WIDTH() call as an
expression for a 'constexpr' variable (tested with type 'unsigned').
By the way, I can't claim any credit for the original idea behind
the macro. The definition here is my revision of a macro called
IMAX_BITS, which showed up in one of the C newsgroups (sorry I
don't have a reference handy). The revised version here limits
its use of constants to values that are guaranteed to be of type
int (not counting of course the constant 0U which is of type
unsigned int rather than int).