using macros to place #ifdef in the code - c++

I am trying to do something like this
#define VB_S #ifdef VERBOSE
#define VB_E #endif
so that in the code instead of writing
#ifdef VERBOSE
cout << "XYZ" << endl;
#endif
I can write
VB_S
cout << "XYZ" << endl;
VB_E
This gives me a compile time error: Stray '#' in the program.
Can anyone put light on what is the right way to do this

You can't put directives inside macros. (# inside a macro as another signification -- it is the stringizing operator and must be followed by a parameter id -- but the restriction is older than that meaning)

You could do something like this:
#ifdef VERBOSE
#define VB(x) x
#else
#define VB(x) do { } while (false)
#endif
VB(cout << "foo");

Similar to Erik's response:
#ifdef VERBOSE
#define VB(...) __VA_ARGS__
#else
#define VB(...) /* nothing */
#endif
Using a variadic macro has the benefit of allowing commas inside the VB() call. Also, AFAIK, you can remove the do...while.

I prefer the following:
#define VERBOSE 1
// or 0, obviously
if (VERBOSE)
{
// Debug implementation
}
This is a little more readable since VB_S doesn't mean anything to the average user, but if (VERBOSE) does.

Related

How to use preprocessor IF on DEFINE that is an ENUM member?

I am struggling with this for a while now, and cant get it to work!
I have a preprocessor define for LOG_LEVEL which defines what logs my program should emit.
I Have a lot of LOG points, so performance is needed,
therefore, no use of runtime check for log_level.
I trimmed my code to the minimal problematic construct which can be played with (here)[https://onlinegdb.com/u39ueqNAI]:
#include <iostream>
typedef enum {
LOG_SILENT=0,
LOG_ERROR,
LOG_WARNING,
LOG_INFO,
LOG_DEBUG
} E_LOG_LEVELS;
// this define is set using -DLOG_LEVEL=LOG_WARNING to the compiler.
#define LOG_LEVEL LOG_WARNING
int main() {
std::cout << "Logging Level Value is " << LOG_LEVEL << std::endl; // output 2 (correctly)
#if LOG_LEVEL==LOG_WARNING
std::cout << "Log Level Warning!" << std::endl; // outputs (correctly)
#endif
#if LOG_LEVEL==LOG_ERROR
std::cout << "Log Level Error!" << std::endl; // outputs (Why ??? )
#endif
return 0;
}
The main issue is that the #if LOG_LEVEL==LOG_* always true.
I also tried #if LOG_LEVEL==2 but this returned FALSE (uff).
what's going on ?
how can I test that a define is an enum value ?
You don't need the preprocessor for this. A normal
if (LOG_LEVEL <= LOG_WARNING)
will not create a runtime test when the condition involves only constants and the build has any optimization at all.
Modern C++ allows you to force the compiler to implement the conditional at compile-time, using if constexpr (...). This will prune away dead branches even with optimization disabled.
Finally, if you insist on using the preprocessor, and you can guarantee that the macro will use the symbolic name (you'll never build with g++ -DLOG_LEVEL=2), then you can
#define STRINGIFY(x) #x
#define STRINGY2(x) STRINGIFY(x)
#define PP_LOG_LEVEL STRINGY2(LOG_LEVEL)
#define LOG_LEVEL_IS(x) STRINGY2(LOG_LEVEL)==STRINGIFY(x)
then either
#if PP_LOG_LEVEL=="LOG_WARNING"
or
#if PP_LOG_LEVEL_IS(LOG_WARNING)
But I would recommend avoiding preprocessor string comparison for this.
If you do use the preprocessor, I recommend checking the actual value against a whitelist and using #error to stop the build in case LOG_LEVEL isn't set to any of the approved names.

Somehow tell compiler to "Do not process line of code"

I'm trying to create a macro for debug logging purposes. Here is an extra simplified version:
#if defined _DEBUG
#define LOG std::cout
#else
#define LOG IGNORETHISLINEOFCODE
#endif
/* ... */
LOG << "Here's some debug code";
I've been thinking of the ways I can tell the compiler to ignore this line of code that starts with "LOG". I'm personally not looking for alternative ways, such as #define LOG( ... ) (void)0. Here's what I've tried:
Overloading the leftshift operator for void as an inline constexpr that does nothing (which still results in it being visible in the disassembly; I don't want that)
Defining LOG as: #define LOG //, but the comment identifier isn't substituted in
Any ideas? Like I said earlier, I don't want any alternatives, such as surrounding all the log code with #if defined _DEBUG
If your version of C++ handles if constexpr I've come to like things along this line for what you're asking.
#include <iostream>
template <bool Log>
struct LOGGER {
template <typename T>
LOGGER& operator<<(T const &t) {
if constexpr (Log)
std::cout << t;
return *this;
}
};
LOGGER<false> LOG;
int main (int argc, char const* argv[])
{
LOG << "A log statement." << '\n';
return 0;
}
Your question and constraint ("I don't want any alternatives") are weirdly specific.
I've been thinking of the ways I can tell the compiler to ignore this line of code that starts with "LOG"
Don't do that, it'll be trivially broken by a multi-line logging statement. Any code that can suddenly break due to otherwise-legal reformatting is best avoided.
Next we have
... which still results in it being visible in the disassembly ...
which shouldn't be true if the code is genuinely dead, you have a decent compiler, and you turn on optimization. It's still some work, though.
The usual solution is something like
#ifdef NDEBUG
#define LOG(EXPR)
#else
#define LOG(EXPR) std::cerr << EXPR
#endif
This is an alternative, but it's not an alternative such as surrounding all the log code with #if defined, so I don't know if it's a problem for you or not.
It does have the advantage of genuinely compiling to nothing at any optimization level.
another possibility based on the compiler optimization abilities:
#define LOG if (DEBUG) std::cout
now you can use
#define DEBUG false
LOG << "hello " << " world 1" << endl;
you should be able to use const bool DEBUG = false as well.
#if defined _DEBUG
#define LOG std::cout
#else
#define LOG /##/
#endif
This works as well. It's the answer to the original question, so I'll mark it as such, but just know that this does not support multiline operations.
I suppose you could do something like the following for multiline operations. I don't know how well it'd work.
#if defined _DEBUG
#define LOG( in ) std::cout << in
#else
#define LOG( in ) /##/
#endif
Better logic would be to define tracer policy, where you can set the logging level at the start of the application and then use the tracing level to make the decision to either log the degug information. Tracing level can be defined as an enum like
enum Tracelevel{CRITICAL, ERROR, INFO, TEST, DEBUG};
setTraceLevel(TraceLevel trcLvl){
_traceLevel = trcLvl;
};
#if defined _DEBUG
if(_traceLevel == DEBUG) {\
#define LOG std::cout
}
#endif
A lightweight logger can be found http://www.drdobbs.com/cpp/a-lightweight-logger-for-c/240147505?pgno=1

Exclude line from compilation via Makro C++

I've got some problem, which might be simple to solve.
I have code like this:
#define _MG_ALL //This might be defined in some other headerfile
#ifndef _MG_ALL
#define MG_ALL <?????>
#else
#define MG_ALL <nothing>
#endif
In the code it is used like this:
ALL foo = thisIsSomeFunc(foo);
This line should only be compiled, if _ALL is defined. This could also be solved by using this:
#ifdef ALL
foo = thisIsSomeFunc(int foo);
#endif
But I would prefer just one short macro in the same line.
What you could do is defining the macro like so:
#ifdef _ALL
#define ALL if(1)
#else
#define ALL if(0)
#endif
When you use it this it will produce code similar to this
ALL std::cout << "Debug Message" << std::endl;
==> if(1) std::cout << "Debug Message" << std::endl;
A good compiler should recognize the constant value in the if-statement and should only compile the right part (1 ==> if part, 0 ==> nothing).

How to redefine a C++ #define macro using information from the macro itself?

Is it possible to redefine a C++ #define macro using information from the macro itself? I tried the code below, but because of the way the macros are evaluated the output was not what I expected.
#include <iostream>
#define FINAL_DEFINE "ABC"
#define NEW_DEFINE FINAL_DEFINE "DEF" // Want ABCDEF
#undef FINAL_DEFINE
#define FINAL_DEFINE NEW_DEFINE // Want ABCDEF, but get empty?
int main ()
{
std::cout << FINAL_DEFINE << std::endl; // Want ABCDEF, but doesn't compile.
}
Macros in macro bodies are never expanded when the macro is defined -- only when the macro is used. That means that the definition of NEW_DEFINE is not "ABC" "DEF", it is exactly what appears on the #define line: FINAL_DEFINE "DEF".
So when you use FINAL_DEFINE, that gets expanded to NEW_DEFINE which then gets expanded to FINAL_DEFINE "DEF". At this point it will not recursively expand FINAL_DEFINE (as that would lead to an infinite loop) so no more expansion occurs.
If your compiler supports push_macro & pop_macro pragma directives, you could do this:
#include <iostream>
#define FINAL_DEFINE "ABC"
#define NEW_DEFINE FINAL_DEFINE "DEF"
int main ()
{
std::cout << FINAL_DEFINE << std::endl; // Output ABC
#pragma push_macro("FINAL_DEFINE")
#define FINAL_DEFINE "XXX"
std::cout << NEW_DEFINE << std::endl; // Output XXXDEF
#pragma pop_macro("FINAL_DEFINE")
}
After preprocessing all FINAL_DEFINE in the code will be replaced with the last thing it defined and then going to compiling step.
So you cannot redefine the macro like you want.
Your compiler should warn you about that.

How can I use #pragma message() so that the message points to the file(lineno)?

In order to add 'todo' items into my code, I want to put a message in the compiler output.
I would like it to look like this:
c:/temp/main.cpp(104): TODO - add code to implement this
in order to make use of the Visual Studio build output functionality to navigate to the respective line by double-clicking it.
But the __LINE__ macro seems to expand to an int, which disallows writing
#pragma message( __FILE__ "("__LINE__"): ..." )
Would there be another way?
Here is one that allows you to click on the output pane:
(There are also some other nice tips there)
http://www.highprogrammer.com/alan/windev/visualstudio.html
// Statements like:
// #pragma message(Reminder "Fix this problem!")
// Which will cause messages like:
// C:\Source\Project\main.cpp(47): Reminder: Fix this problem!
// to show up during compiles. Note that you can NOT use the
// words "error" or "warning" in your reminders, since it will
// make the IDE think it should abort execution. You can double
// click on these messages and jump to the line in question.
#define Stringize( L ) #L
#define MakeString( M, L ) M(L)
#define $Line MakeString( Stringize, __LINE__ )
#define Reminder __FILE__ "(" $Line ") : Reminder: "
Once defined, use like so:
#pragma message(Reminder "Fix this problem!")
This will create output like:
C:\Source\Project\main.cpp(47): Reminder: Fix this problem!
just whipped this up now, and it sure beats my old solution of using #error :D
#define _STR(x) #x
#define STR(x) _STR(x)
#define TODO(x) __pragma(message("TODO: "_STR(x) " :: " __FILE__ "#" STR(__LINE__)))
you can modify this how ever you like/to whatever suits your needs.
An example of its usage:
//in code somewhere
TODO(Fix this);
output in the console pane:
1>TODO: Fix this :: c:\users\administrator\documents\visual studio 2008\projects\metatest\metatest\metatest.cpp#33
only downside is you can't jump to the line of this (by double clicking the message in the console pane) using __pragma (but testing with #pragma it doesn't seem to be the case anyways...)
On Visual C++ you can just do
#pragma message(__FILE__ "(" _CRT_STRINGIZE(__LINE__) ")" ": warning: [blah]")
_CRT_STRINGIZE is often already defined in some header, but if it's not, you can define it:
#define _CRT_STRINGIZE_(x) #x
#define _CRT_STRINGIZE(x) _CRT_STRINGIZE_(x)
This one allows it to be used without #pragma (Microsoft specific I think) and when you click it takes you to the line since it shows the file and line number just like a regular err/warning message does since none of the other ones seem to do this. This used to work without the __pragma but newer versions of msvc require it. Ive been using it since sometime in the 90's. I use Visual Studio 2013
#define MacroStr(x) #x
#define MacroStr2(x) MacroStr(x)
#define Message(desc) __pragma(message(__FILE__ "(" MacroStr2(__LINE__) ") :" #desc))
example :
Message("Need to add unit testing here")
output:
1> c:\source\include\mithrilsoftware.h(180) :"Need to add unit testing here"
This is an addendum to the answer for those who find it tedious to punch in #pragma directives every-time they need to put a bookmark in the code: You can save a few keystrokes by whipping up a macro to do this for you! While in general, you cannot have a #pragma directive within macros, MS C/C++ compilers 2008 and above do support a special vendor-specific extension called the __pragma which can be used with macros. See Pragma Directives and the __Pragma Keyword.
I use something akin to the following on a daily basis:
#define STR2(x) #x
#define STR1(x) STR2(x)
#define LOC __FILE__ "("STR1(__LINE__)") : Warning Msg: "
#define WARNING_BUILDER(x) __FILE__ "("STR1(__LINE__)") : Warning Msg: " __FUNCTION__ " requires " #x
#define WREVIEW WARNING_BUILDER(review)
#define WUT WARNING_BUILDER(unit-testing)
#ifdef SPECIAL_WARNINGS
#ifdef SPECIAL_WARNINGS_REVIEW
#define MARK_FOR_REVIEW() do { \
__pragma(message( WREVIEW )) \
} while (0)
#else
#define MARK_FOR_REVIEW
#endif
#ifdef SPECIAL_WARNINGS_UNIT_TEST
#define MARK_FOR_UNIT_TEST() do { \
__pragma(message( WUT )) \
} while (0)
#else
#define MARK_FOR_UNIT_TEST
#endif
#endif
// uncomment/set in build-environment to enable special warnings
//#define SPECIAL_WARNINGS
#ifdef SPECIAL_WARNINGS
// uncomment/set in build-environment if you want only code review warnings
//#define SPECIAL_WARNINGS_REVIEW
// uncomment/set in build-environment if you want only unit-test warnings
//#define SPECIAL_WARNINGS_UNIT_TEST
#endif
int main()
{
MARK_FOR_REVIEW();
MARK_FOR_UNIT_TEST();
}
You can easily extend it to suit your needs and add more warnings. The good part of having such a system is that you can selectively turn-on say, only code-review items and not have to worry about anything else by setting the appropriate macro in the build settings.
Use the # token. I've posted an example from MSDN below:
// collisions.h
#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
#define __LOC__ __FILE__ "("__STR1__(__LINE__)") : Warning Msg: "
// collisions.cpp
#pragma message(__LOC__"Need to do 3D collision testing")