Related to my question Alternative to expanding templates in a switch statement trying to get Boost.Preprocessor to do a nested interation over a sequence.
#include <boost/preprocessor.hpp>
#include <iostream>
#define LASERTYPE_VALUES (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER)
enum LaserType
{
BOOST_PP_SEQ_ENUM(LASERTYPE_VALUES)
};
#define LT_NESTED(maR, maToplevelType, maNestedType) \
std::cout << "Test nested: first=" << LaserType(maToplevelType) << " second=" << LaserType(maNestedType) << " \n";
#define LT_TOPLEVEL(maR, maUnused, maType) \
std::cout << "Test toplevel: " << LaserType(maType) << " \n"; \
BOOST_PP_SEQ_FOR_EACH_R(maR, LT_NESTED, maType, LASERTYPE_VALUES);
int main() {
BOOST_PP_SEQ_FOR_EACH(LT_TOPLEVEL, %%, LASERTYPE_VALUES);
}
This leads to this error:
test-pp.cpp: In function ‘int main()’:
test-pp.cpp:15:32: error: ‘LT_NESTED’ was not declared in this scope
BOOST_PP_SEQ_FOR_EACH_R(maR, LT_NESTED, maType, LASERTYPE_VALUES);
^
/usr/include/boost/preprocessor/seq/for_each.hpp:49:57: note: in expansion of macro ‘LT_TOPLEVEL’
# define BOOST_PP_SEQ_FOR_EACH_M_I(r, macro, data, seq) macro(r, data, BOOST_PP_SEQ_HEAD(seq))
^
test-pp.cpp:4:39: error: ‘EXCIMER’ cannot be used as a function
#define LASERTYPE_VALUES (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER)
^
test-pp.cpp:15:51: note: in expansion of macro ‘LASERTYPE_VALUES’
BOOST_PP_SEQ_FOR_EACH_R(maR, LT_NESTED, maType, LASERTYPE_VALUES);
Reordering the macros doesn't help. There's something fundamentally wrong here, and it's likely trivial, but I haven't yet figured out how to do this and haven't seen any decent examples. If anyone had any suggestions, I'd be very interested to know what I'm doing wrong here.
https://groups.google.com/forum/#!topic/boost-list/jhN4NE9VAtg indicates that I might be running into reentrancy problems. It looks like I might be able to use BOOST_PP_FOR directly for the top level macro perhaps. If anyone had an example of that, it would be really useful.
I found a workaround in https://groups.google.com/forum/#!topic/boost-devel-archive/Tbcs4nn4sPE which gives this solution:
#include <boost/preprocessor.hpp>
#include <iostream>
#define LASERTYPE_VALUES (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER)
enum LaserType
{
BOOST_PP_SEQ_ENUM(LASERTYPE_VALUES)
};
#define PP_SEQ_FOR_EACH_R_ID() BOOST_PP_SEQ_FOR_EACH_R
#define PP_DEFER(x) x BOOST_PP_EMPTY()
#define LT_NESTED(maR, maToplevelType, maNestedType) \
std::cout << "Test nested: first=" << LaserType(maToplevelType) << " second=" << LaserType(maNestedType) << " \n";
#define LT_TOPLEVEL(maR, maUnused, maType) \
std::cout << "Test toplevel: " << LaserType(maType) << " \n"; \
PP_DEFER(PP_SEQ_FOR_EACH_R_ID)()(maR, LT_NESTED, maType, LASERTYPE_VALUES);
int main() {
BOOST_PP_EXPAND(BOOST_PP_SEQ_FOR_EACH(LT_TOPLEVEL, %%, LASERTYPE_VALUES));
}
It's a bit esoteric but it compiles and functions as required.
1.#define debug(...) printf( __VA_ARGS__)
2.#define debug(...) std::cout<< __VA_ARGS__
Apparently, 1 is ok, 2 will get error when compiles.
Is there any possibility to use "std::cout" with variable arguments?
What's the point of this macro?
'debug' macro use to print something to debug the code.
void test(const classtype1 &obj1,const classtype2 &obj2)
{
// rewrite operator<<
debug(obj1,obj2);
//if use printf, I must call tostring method(or something likes that) to
//series the object to string.
debug(obj1.tostring(),obj2.tostring());
...
}
You can do something like:
#define DEBUG(x) do { std::osacquire( std::cerr ) << __FILE__ << ":" << __LINE__ << " " << x << std::endl; } while (0);
And then wherever you want to use the macro:
DEBUG( obj1.tostring() + " some stuff " + obj2.tostring() )
In the absence of help from Google, I wonder if someone could tell me if it is possible to create a C++ (g++) debug macro that acts like, for example, an "improved" std::cout. Idea is to accept args via << and to append some text so that
DBG << "Hello" << world;
might produce
myfile.cpp 1420 Hello world
I know there are logging libraries(?)/macros(?) out there that do this sortof thing. I'm interested in how it's done, not using some package.
Your macro could create a temporary variable which invokes endl on destruction. The temporary will stick around until the enclosing expression ends, typically at the ;.
#include <iostream>
struct X {
~X() { std::cout << std::endl; }
};
#define DBG (X(), std::cout << __FILE__ << " " << __LINE__ << " ")
int main () {
std::string world(", world");
DBG << "Hello" << world;
}
How about:
#define DBG std::cout << __FILE__ << " " << __LINE__ << " "
http://ideone.com/mN5n3
Close enough! Unfortunatelly, you have to declare the variable world beforehand.
The idea behind a debug macro is that it should compile to nothing if you are in release mode. Try this;
#ifdef _DEBUG
#define MESSAGE(x) (std::cout << __FILE__ << " " << __LINE__ << " " << x);
#else
#define MESSAGE(x) ;
#endif
int _tmain(int argc, _TCHAR* argv[])
{
MESSAGE("Hello");
return 0;
}
When you are in release mode, MESSAGE(x) will have no effect, but in debug mode, you will get a message to the command line.
I saw this debug print for c++ here on stackoverflow but I can't comment it (I'm a newbie):
#ifdef DEBUG
#define dout cout
#else
#define dout 0 && cout
#endif
It is used like this:
dout << "in foobar with x= " << x << " and y= " << y << '\n';
At first sight I liked it, but I compile with -Wall, so I get a lot of warnings like
test1.cc:30:46: warning: statement has no effect [-Wunused-value]
Is there a way to reconcile -Wall and the stream oriented debug print?
This can be further refined, but try this as starting point:
#ifdef DEBUG
#define LOG_DEBUG( stuff ) { std::cout << stuff << std::endl; }
#else
#define LOG_DEBUG( stuff )
#endif
Then later in the code:
LOG_DEBUG( __FILE__ << " bla bla bla " << foo );
I'm looking for a way to add custom messages to assert statements.
I found this questions Add custom messages in assert? but the message is static there. I want to do something like this:
assert((0 < x) && (x < 10), std::string("x was ") + myToString(x));
When the assertion fails I want the normal output plus for example "x was 100".
You are out of luck here. The best way is to define your own assert macro.
Basically, it can look like this:
#ifndef NDEBUG
# define ASSERT(condition, message) \
do { \
if (! (condition)) { \
std::cerr << "Assertion `" #condition "` failed in " << __FILE__ \
<< " line " << __LINE__ << ": " << message << std::endl; \
std::terminate(); \
} \
} while (false)
#else
# define ASSERT(condition, message) do { } while (false)
#endif
This will define the ASSERT macro only if the no-debug macro NDEBUG isn’t defined.
Then you’d use it like this:
ASSERT((0 < x) && (x < 10), "x was " << x);
Which is a bit simpler than your usage since you don’t need to stringify "x was " and x explicitly, this is done implicitly by the macro.
There are some old tricks to include messages without writing your own routines:
The first is this:
bool testbool = false;
assert(("this is the time", testbool));
There is also:
bool testbool = false;
assert(testbool && "This is a message");
The first one works, because the inside parens expression result is the value of 'testbool'.
The second one works, because the value of the string is going to be non-zero.
A better alternative is to teach the debugger to stop on assert when it fails, then you could examine not only the x value but any other information including call stack. Perhaps, this is what you are really looking for.
Sample implementation is mentioned here Ways to show your co-programmers that some methods are not yet implemented in a class when programming in C++
#define ASSERT_WITH_MESSAGE(condition, message) do { \
if (!(condition)) { printf((message)); } \
assert ((condition)); } while(false)
Extending on Kondrad Rudolph's answer:
#include <iostream>
#ifdef NDEBUG
#define assert(condition, message) 0
#else
#define assert(condition, message)\
(!(condition)) ?\
(std::cerr << "Assertion failed: (" << #condition << "), "\
<< "function " << __FUNCTION__\
<< ", file " << __FILE__\
<< ", line " << __LINE__ << "."\
<< std::endl << message << std::endl, abort(), 0) : 1
#endif
void foo() {
int sum = 0;
assert((sum = 1 + 1) == 3, "got sum of " << sum << ", but expected 3");
}
int main () {
foo();
}
Output is...
Assertion failed: ((sum = 1 + 1) == 3), function foo, file foo.cpp, line 13.
got sum of 2, but expected 3
zsh: abort ./a.out
which is similar to what the std::assert macro outputs on my system just with the additional user defined message
For the sake of completeness, I published a drop-in 2 files assert macro implementation in C++:
#include <pempek_assert.h>
int main()
{
float min = 0.0f;
float max = 1.0f;
float v = 2.0f;
PEMPEK_ASSERT(v > min && v < max,
"invalid value: %f, must be between %f and %f", v, min, max);
return 0;
}
Will prompt you with:
Assertion 'v > min && v < max' failed (DEBUG)
in file e.cpp, line 8
function: int main()
with message: invalid value: 2.000000, must be between 0.000000 and 1.000000
Press (I)gnore / Ignore (F)orever / Ignore (A)ll / (D)ebug / A(b)ort:
Where
(I)gnore: ignore the current assertion
Ignore (F)orever: remember the file and line where the assertion fired and
ignore it for the remaining execution of the program
Ignore (A)ll: ignore all remaining assertions (all files and lines)
(D)ebug: break into the debugger if attached, otherwise abort() (on Windows,
the system will prompt the user to attach a debugger)
A(b)ort: call abort() immediately
You can find out more about it there:
blog post
GitHub project
Hope that helps.
Yes, this is possible.
To enable expression like better_assert((0 < x) && (x < 10), std::string("x was ") + myToString(x));, we are supposed to have a corresponding macro in a form of
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? \
(void)0 : print_assertion(std::cerr, \
"Assertion failure: ", #EXPRESSION, " in File: ", __FILE__, \
" in Line: ", __LINE__ __VA_OPT__(,) __VA_ARGS__))
in which print_assertion is a proxy function to do the assertion. When the EXPRESSION is evaluated false, all the debug information, the __VA_ARGS__, will be dumped to std::cerr. This function takes arbitrary numbers of arguments, thus we should implement a variadic templated function:
template< typename... Args >
void print_assertion(std::ostream& out, Args&&... args)
{
out.precision( 20 );
if constexpr( debug_mode )
{
(out << ... << args) << std::endl;
abort();
}
}
In the previous implementation, the expression (out << ... << args) << std::endl; make use of fold expression in C++17 (https://en.cppreference.com/w/cpp/language/fold); the constant expression debug_mode is related to the compilation options passed, which is can be defined as
#ifdef NDEBUG
constexpr std::uint_least64_t debug_mode = 0;
#else
constexpr std::uint_least64_t debug_mode = 1;
#endif
It also worth mentioning that the expression if constexpr( debug_mode ) makes use of constexpr if (https://en.cppreference.com/w/cpp/language/if) imported since C++17.
To wrap everything up, we have:
#ifdef NDEBUG
constexpr std::uint_least64_t debug_mode = 0;
#else
constexpr std::uint_least64_t debug_mode = 1;
#endif
template< typename... Args >
void print_assertion(std::ostream& out, Args&&... args)
{
out.precision( 20 );
if constexpr( debug_mode )
{
(out << ... << args) << std::endl;
abort();
}
}
#ifdef better_assert
#undef better_assert
#endif
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? (void)0 : print_assertion(std::cerr, "Assertion failure: ", #EXPRESSION, " in File: ", __FILE__, " in Line: ", __LINE__ __VA_OPT__(,) __VA_ARGS__))
A typical test case demonstrating its usage can be:
double const a = 3.14159265358979;
double const b = 2.0 * std::asin( 1.0 );
better_assert( a==b, " a is supposed to be equal to b, but now a = ", a, " and b = ", b );
This will produce something error message like:
Assertion failure: a==b in File: test.cc in Line: 9 a is supposed to be equal to b, but now a = 3.1415926535897900074 and b = 3.141592653589793116
[1] 8414 abort (core dumped) ./test
And the full source code is available in this repo: https://github.com/fengwang/better_assert
To take on Feng Wang answer, in newer versions of C++, anything inline is going to be optimized out. So you can have an inline function in a header file which does all the work.
inline constexpr void NOT_USED()
{
}
template <class T, class ...ARGS>
inline constexpr void NOT_USED(T && first, ARGS && ...args)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
static_cast<void>(first);
#pragma GCC diagnostic pop
NOT_USED(args...);
}
template<typename ... ARGS>
void SAFE_ASSERT(bool test_result, ARGS &&... args)
{
#ifdef _DEBUG
if(test_result)
{
(std::cerr << ... << args) << std::endl;
abort();
}
#else
NOT_USED(test_result, args...);
#endif
}
Some comments:
If _DEBUG is not defined, the function becomes empty so it can be optimized out 100%
If you call the function with a side effect, the non-debug code still works:
my_assert(c++ < --z, "the #define versions do not behave similarly");
These side effects are clearly visible here. However, if you call a function, it could be really difficult to know whether something happens in the function which was not otherwise expected.
There are ways to prevent such side effects from happening, though (Example). But all in all, in some cases, you need to call a function for the test and it may have a side effect and therefore needs to not be optimized out in non-debug code.
I use abort() because I know that stops the debugger properly, std::terminate() is the C++ way which in modern systems does the same thing, but if std::terminate() doesn't work for your debugger the abort() will.
The NOT_USED() is to avoid warnings about unused function parameters (if you don't have that warning, you may end up with expected bugs).
I have an implementation in snapdev: see safe_assert.h and not_used.h.
going along with Konrad Rudolf's answer you can do it a bit more concise with
#include <assert.h>
#include <stdio.h>
#define ASSERT(condition,...) assert( \
condition|| \
(fprintf(stderr,__VA_ARGS__)&&fprintf(stderr," at %s:%d\n",__FILE__,__LINE__)) \
);
which also works in C,
it works using the general idea from some of the answers to the question you linked, but the macro allows it to be a little more flexible