Is there a way to define a constexpr before an #if compiler directive as its input?
In other words, can #if have inputs from constexpr? If not, does it mean #if directive is evaluated before the constexpr?
constexpr int enable_debug = true;
#if (enable_debug)
std::string debug_logs;
#endif
for(int i=0;i<10;i++) {
f(i);
#if (enable_debug)
debug_logs += std::to_string(i);
#endif
}
#if (enable_debug)
std::court << debug_logs;
#endif
This question has two objectives:
Is "directive time" or "pragma time" earlier than compile time?
I want to build some code only conditionally, but the code defined a variable, so I cannot use if constexpr().
No, there is no way to do this. Preprocessor commands are applied in an earlier phase of translation than the evaluation (or even full parsing) of variable definitions. #if can do normal integer arithmetic and comparisons, and can expand preprocessor macros which were created with #define, but it cannot inspect non-preprocessor code.
You'll either need to make enable_debug a preprocessor macro, or change from preprocessor conditionals to if or if constexpr (which, of course, have their own limitations).
Related
I wrote this simple program
#include <time.h>
int main()
{
#if ((clock_t)1000)
int x = 10;
#endif
return 0;
}
On compilation, I see the following error:
Error C1012 unmatched parenthesis: missing ')'
Why am I getting this error?
Changing the line from:
#if ((clock_t)1000)
to:
#if (clock_t)1000
resolves the compilation error.
But I can't do that, since ((clock_t)1000) is defined as a macro using the #define directive in the limits.h header file as :
#define CLOCKS_PER_SEC ((clock_t)1000)
and I need to use that directly.
EDIT:
Please pardon me for framing the question in such an unclear way.
Reframing my question now:
I have the following code:
#include <time.h>
#define DUMMY_CLOCKS_PER_SEC ((clock_t)1000)
int main()
{
#if CLOCKS_PER_SEC != DUMMY_CLOCKS_PER_SEC
#error "out of sync"
#endif
return 0;
}
But this gives the compilation error:
Error C1012 unmatched parenthesis: missing ')'
The preprocessor doesn't know anything about C++ datatypes, and doesn't understand cast expressions. It's used for simple text processing, and == and != can only compare single tokens.
Do the comparison in C++, not the preprocessor.
static_assert(CLOCKS_PER_SEC == DUMMY_CLOCKS_PER_SEC, "out of sync");
int main() {
return 0;
}
Don't worry about the runtime performance overhead. Since both macros expand to literals, the compiler will optimize it away.
You are confusing a preprocessor macro definition (CLOCKS_PER_SEC) with its expansion (that is implementation defined, and in your case seems to be ((clock_t)1000)).
It's not very clear what you want to do in your code.
If you want to check if this macro is defined, you can use the preprocessor #ifdef, e.g.:
#ifdef CLOCKS_PER_SEC
// your code
#endif
Anyway, this CLOCKS_PER_SEC macro is defined by the standard, so it should be always defined in a standard-compliant time.h library implementation.
If you have something different in your mind, please clarify your goal.
EDIT Based on your clarifying comment below, you may want to use an if to compare the values (expansions) of these two macros:
if (DUMMY_CLOCKS_PER_SEC != CLOCKS_PER_SEC) {
...
} else {
...
}
((clock_t)1000) is defined as a macro using the #define directive in the limits.h header file as :
#define CLOCKS_PER_SEC ((clock_t)1000)
The file does not define a macro named ((clock_t)1000). It defines a macro named CLOCKS_PER_SEC. ((clock_t)1000) is the value of the macro.
((clock_t)1000) is not a macro and is something that cannot be used in an #if directive.
Thanks for all the responses everyone.
Another solution I figured out for this problem is to use constexpr specifier which is a feature of c++11. ConstExpr allows us to evaluate the value of a variable or a function at compile time.
Changing the code from:
#if CLOCKS_PER_SEC != DUMMY_CLOCKS_PER_SEC
#error "out of sync"
#endif
to the following resolves the issue:
constexpr int DUMMY_CLOCK_NOT_EQUAL = (DUMMY_CLOCKS_PER_SEC != CLOCKS_PER_SEC) ? 1 : 0;
#if DUMMY_CLOCK_NOT_EQUAL
#error "out of sync"
#endif
#define TML_ID - No value is assigned to TML_ID. There's no problem in compilation or building executables. will this assign any default value like null to TML_ID or will TML_ID be considered undefined ?
This simply says that the macros is defined, so you can do this in main or any other function:
#ifdef TML_ID
printf("Defined!\n");
#else
printf("Undefined!\n");
#endif
#define doesn't assign a value to the macro. In fact, it's considered as a flag to tell the compiler that a specific macro has been defined.
You can imagine it as if you declare a variable without assigning any values. It will have a garbage value but it will reserve a space in the memory. But in case of a macro, the definition won't reserve a space. Only a hint for the compiler.
Without assigned a value, macros in this way are usually used to prevent including same .h file multiple times, this way:
#ifndef _FILENAME
#define _FILENAME
//declaration code
#endif
If some .cpp file includes, for example, two different .h files, which both include our .h file, then .cpp will have only one copy of declaration code, since second time _FILENAME macro will be DEFINED, and declaration code will be skipped.
#define MACRO
defines a macro named MACRO. It has no content, so if you wrote something like std::cout << MACRO you'd get an error because there's nothing there. This is often used to conditionally use new keywords:
#if CPP_VERSION_C11
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif
void f() NOEXCEPT {
// whatever
}
There are two other ways you can use such a macro. You can check whether it's defined:
#ifdef MACRO
// code for one branch
#else
// code for other branch
#endif
For that code, since MACRO has been defined, the preprocessor will look at the code in the first branch, and skip the code in the second branch. If MACRO had not been defined, it would skip the code in the first branch rather than the second. You can also do the same thing this way:
#if defined(MACRO)
or you can use it in a constant expression in a preprocessor directive:
#if MACRO
// code for one branch
#else
// code for other branch
#endif
here, MACRO gets the value 0, the #if sees the value 0, and the preprocessor skips the first branch. The same thing occurs in more complex expressions:
#if MACRO + 1 > 0
// code for one branch
#else
// code for other branch
#endif
Here, MACRO has the value 0, MACRO + 1 has the value 1, and the first branch will be selected.
#include < iostream >
#define MY_CHK_DEF(flag) \
#ifdef (flag) \
std::cout<<#flag<<std::endl; \
#else \
std::cout<<#flag<<" ,flag not define"<<std::endl; \
#endif
int main()
{
MY_CHK_DEF(FLAG_1);
MY_CHK_DEF(FLAG_2);
MY_CHK_DEF(FLAG_3);
...
}
complier report:
main.cpp:3:24: error: '#' is not followed by a macro parameter
any ideas?
Thanks
You can't do it. #if, #else, and #endif must be the first tokens on the logical line. Your definition is just one logical line, so it doesn't work,
You have to do it the other way round(defining the macro for each #if/#ifdef/#else condition(if you nest you have to put a definition on each branch). You probably should define it at every logical branch or it will fail to compile when you try to adjust a rarely adjusted flag. You can #define noops like this. Note to be careful not to wrap expressions with side effects into #define 'd macros that reduce to a noop when the debug flag is on, or your program may not work right.
#define N(x)
#include < iostream >
#ifdef (flag)
#define MY_CHK_DEF(flag)
std::cout<<#flag<<std::endl;
#else
#define MY_CHK_DEF(flag) \
std::cout<<#flag<<" ,flag not define"<<std::endl;
#endif
int main()
{
MY_CHK_DEF(FLAG_1);
MY_CHK_DEF(FLAG_2);
MY_CHK_DEF(FLAG_3);
...
}
C preprocessor is single-pass and #define creates a pretty dumb replacement that isn't further processed - your MY_CHK_DEF(flag) macro inserts the #if statement inline into preprocessed code that is interpreted by C compiler and not valid C.
You can either rephrase it to be one-pass, or if you can't, run through preprocessor twice, manually - once through cpp -P and the second time through normal compilation process.
You actually can do this if you use BOOST processor header lib.. it provides a BOOST_PP_IF macro allow this type of decisions.
http://www.boost.org/doc/libs/1_53_0/libs/preprocessor/doc/ref/if.html
I have a code that runs on an embedded system and it has to run really fast. I know C and macros, and this particular project is coded mostly in C but it also uses C++ templates [increasingly more]. There is an inline function:
inline my_t read_memory(uint32 addr) {
#if (CURRENT_STATE & OPTIMIZE_BITMAP)
return readOptimized(addr);
#else
return MEMORY[addr];
#endif
}
This function reads from memory in an optimized fashion or conventional fashion based on the current state and a bitmap that tells whether to use optimization in a specific state or not.
#define STATE_A 0x0001
#define STATE_B 0x0010
#define STATE_C 0x0100
#define STATE_D 0x1000
#define OPTIMIZE_BITMAP 0x1010 // optimize states d and b
and during the course of execution (ok, compilation), I tried to redefine CURRENT_STATE like so:
int main(){
#define CURRENT_STATE STATE_A
do_a();
#undef CURRENT_STATE
#define CURRENT_STATE STATE_B
do_b();
....
}
All do_X() functions make read_memory() calls. I could not make this approach work. The value of current state is always STATE_A as I can see when I use #warning statements. This is not my question, although if you can help me with this I'll be double happy. So, my question is, is there a way to do this kind of thing using templates instead of macros?
Some more info: I have to use an inline function because I cannot export MEMORY[] and this is a library function. I really prefer not to modify the function prototype (like read_memory()...) but it will do. Also, pardon my obscurity.
many thanks,
The inline function will be parsed once, at the point in the translation unit where it is declared, and the state of the macros at that point will be used. Calling the function multiple times with the macros defined differently will not change the definition of the function.
You can do this with a template though --- if you pass the "current state" as a template parameter then you can use a different instantiation at each call point:
template<unsigned state>
inline my_t read_memory(uint32 addr) {
if(state & OPTIMIZE_BITMAP)
return readOptimized(addr);
else
return MEMORY[addr];
}
int main(){
read_memory<STATE_A>(some_addr);
read_memory<STATE_B>(some_addr);
....
}
The compiler will realise that state & OPTIMIZE_BITMAP is a constant and optimize out one or other branch of the if for each template instantiation.
I think you may be misunderstanding what the compiler (or rather, the preprocessor) does with #defines.
Your example (quoted below) is not useful, because CURRENT_STATE is not used between the #define and the #undef. The preprocessor isn't 'executing' your code, or expanding do_a() inline at this point. #defines and macro expansion can only occur EXACTLY IN THE ORDER OF THE LINES IN YOUR SOURCE.
#define CURRENT_STATE STATE_A
do_a();
#undef CURRENT_STATE
Here's a preprocessor-based solution, if templates fill you with horror. Let's assume that do_a() should use the optimised version.
inline my_t read_memory(uint32 addr)
{
return MEMORY[addr];
}
inline my_t read_memory_optimized(uint32 addr)
{
return readOptimized(addr);
}
Now, create DO_CONFIG.H
#if defined(DO_A) || (defined(DO_C) || ...)
#define READ_MEMORY read_memory_optimized
#else
#define READ_MEMORY read_memory
In DO_A.C, add this at the top
#define DO_A
#include DO_CONFIG.H
...and use x=READ_MEMORY(addr) instead of x=read_memory(addr). To switch from optimised to non-optimised, just change DO_CONFIG.H
For some reason I need to temporarily disable some macros in a header file and the #undef MACRONAME will make the code compile but it will undef the existing macro.
Is there a way of just disabling it?
I should mention that you do not really know the values of the macros and that I'm looking for a cross compiler solution (should work at least in GCC and MSVC).
In MSVC you could use push_macro pragma, GCC supports it for compatibility with Microsoft Windows compilers.
#pragma push_macro("MACRONAME")
#undef MACRONAME
// some actions
#pragma pop_macro("MACRONAME")
Using just the facilities defined by Standard C (C89, C99 or C11), the only 'disable' mechanism is #undef.
The problem is there is no 're-enable' mechanism.
As others have pointed out, if the header file containing the macro definitions is structured so that it does not contain any typedef or enum declarations (these cannot be repeated; function and variable declarations can be repeated), then you could #undef the macro, do what you need without the macro in effect, and then re-include the header, possibly after undefining its protection against reinclusion.
If the macros are not defined in a header, of course, you are stuck until you refactor the code so that they are in a header.
One other trick is available - if the macros are function-like macros and not object-like macros.
#define nonsense(a, b) b /\= a
int (nonsense)(int a, int b)
{
return (a > b) ? a : b;
}
The function nonsense() is defined fine, despite the macro immediately before it. This is because a macro invocation - for a function-like macro - must be immediately followed by an open parenthesis (give or take white space, possibly including comments). In the function definition line, the token after 'nonsense' is a close parenthesis, so it is not an invocation of the nonsense macro.
Had the macro been an argument-less object-like macro, the trick would not work:
#define nonsense min
int (nonsense)(int a, int b)
{
// Think about it - what is the function really called?
return (a > b) ? a : b;
}
This code defines a bogus function that's called min and is nonsensical. And there's no protection from the macro.
This is one of the reasons why the standard is careful to define which namespaces are reserved for 'The Implementation'. The Implementation is allowed to define macros for any purpose it desires or needs, of any type (function-like or object-like) it desires or needs, provided those names are reserved to the implementation. If you as a consumer of the services of The Implementation try to use or define a name reserved to the implementation, you must be aware that your code will probably break sooner or later, and that it will be your fault, not the fault of The Implementation.
Macros make my knees go weak, but wouldn't the most universal solution be to restructure your code so that you wouldn't need to reenable the macro again in the same source file? Wouldn't it be possible to extract some code into a separate function and a separate source file where you can undef the offending macro.
The macros come from some header file, so you should have access to their values. You can then do something like
#include <foo.h> // declares macro FOO
// Do things with FOO
#undef FOO
// do things without FOO
#include <foo.h> // reenable FOO
Your header should then be designed along these lines
#ifndef FOO
#define FOO do_something(x,y)
#endif
EDIT:
You may think that it's that easy:
#ifdef macro
#define DISABLED_macro macro
#undef macro
#endif
// do what you want with macro
#ifdef DISABLED_macro
#define macro DISABLED_macro
#endif
But it's not (like the following example demonstrates)!
#include <iostream>
#include <limits>
#include <windows.h>
#ifdef max
#define DISABLED_max max
#undef max
#endif
int main()
{
std::cout << std::numeric_limits<unsigned long>::max() << std::endl;
#ifdef DISABLED_max
#define max DISABLED_max
#endif
std::cout << max(15,3) << std::endl; // error C3861: "max": identifier not found
return 0;
}
Using #undef on the macro and re-including the original header is also not likely to work, because of the header guards.
So what's left is using the push_macro/pop_macro #pragma directives.
#pragma push_macro("MACRO")
#undef MACRO
// do what you want
#pragma pop_macro("MACRO")
There are specific rules for function-like macroses invokation in C/C++ language.
The function-like macroses have to be invoked in the following way:
Macros-name
Left parethesis
One token for each argument separated by commas
Each token in this list can be separared from another by whitespaces (i.e. actual whitespaces and commas)
With one trick you "disable preprocessor mechanism" with breaking rules for function-like macro invokation, but be still within a rules of function calling mechanism...
#include <iostream>
using namespace std;
inline const char* WHAT(){return "Hello from function";}
#define WHAT() "Hello from macro"
int main()
{
cout << (*WHAT)() << "\n"; // use function
cout << (WHAT)() << "\n"; // use function
cout << WHAT () << "\n"; // use macro
return 0;
}