The Linux kernel has even a way to determine whether the expression is compile-time, WITHOUT aborting compilation in either case.<p>The trick is this (copied vebratim from Linux):<p>#define __is_constexpr(x) (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))<p>Explanation: if x is a constant expression, then multiplying it by zero yields a constant 0, and casting a constant 0 to void* makes a null pointer constant. And the ternary expression, if one of its sides is a null pointer constant, collapses to the type of the other side (thus the type of the returned pointer will be int*, and the sizeof will match). And if x was not constant, then the lefthand side would not be considered a null pointer constant by type inference, the type of the ternary expression will be void*, and the sizeof check will not match.<p>With a few more clever tricks, it's even possible to implement a compile-time "type ternary expression", like this: TYPE_IF(2 * 2 == 4, int, long). This is left as an exercise for the reader.
> This works. But both gcc and clang warn about the enum being anonymous... even though that's exactly what I wanted to do. And this cannot be silenced with #pragma since it's a macro, so the warning occurs at the location where the macro is invoked.<p>You can use _Pragma instead of #pragma. E.g.<p><pre><code> #define C(x) ( \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wvisibility\"") \
(x) + 0*sizeof(void (*)(enum { tmp = (int)(x) })) \
_Pragma("clang diagnostic pop") \
)
</code></pre>
EDIT: Alas, GCC is a little pickier about where _Pragma is allowed so you may need to use a statement expression. Also, it seems GCC 14 doesn't have a -W switch that will disable the anonymous enum warning.
I thought this would work:<p>#define C(x) (sizeof(char[x]), x)<p>sizeof is a compile-time operation so x need to be known at compile time.<p>It didn't work as expected. It turns out there is an exception and the standard says that sizeof is actually calculated at runtime specifically for variable length arrays:<p>> The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
It's remarkable that people will say that doing this kind of thing is better than learning a language which actually lets you enforce this with the type system.<p>(or even just insist that users use the version of the language which supports "constexpr"!)