I would like to define a macro to concat __func__ (or __FUNCTION__) with __LINE__:
The following works fine:
// macro_test.cc
#include <iostream>
#define STR2(X) #X
#define STR(X) STR2(X)
#define FILE_LOCATION __FILE__ ":" STR(__LINE__) " "
int main() {
std::cout << FILE_LOCATION << "is <file_name>:<line_number>" << std::endl;
return 0;
}
And here is the output
$ ./a.out
macro_test.cc:8 is <file_name>:<line_number>
However the following gives a compilation error (I just replaced __FILE__ with __func__):
// macro_test.cc
#include <iostream>
#define STR2(X) #X
#define STR(X) STR2(X)
#define FUNC_LOCATION __func__ ":" STR(__LINE__) " "
int main() {
std::cout << FUNC_LOCATION << "is <function_name>:<line_number>" << std::endl;
return 0;
}
~$ gcc macro_test.cc
macro_test.cc: In function ‘int main()’:
macro_test.cc:5:32: error: expected ‘;’ before string constant
#define FUNC_LOCATION __func__ ":" STR(__LINE__) " "
^
macro_test.cc:8:16: note: in expansion of macro ‘FUNC_LOCATION’
std::cout << FUNC_LOCATION << "is <function_name>:<line_number>" << std::endl;
Does anyone know the reason for this and how can I achieve this?
I am using gcc 5.4.0 on Linux (Ubuntu 18.04).
gives a compilation error [...] anyone know the reason for this
__func__ is a variable:
static const char __func__[] = "function-name";
It is not to a (string) literal (to which for example __FILE__ "expands".)
(docs are here: https://gcc.gnu.org/onlinedocs/gcc/Function-Names.html)
Instead of trying to stitch together incompatible types into a single string, you could have an immediately invoked function expression (borrowing from JavaScript terminology) as the macro implementation.
Since it is being immediately executed, I pass in the two preprocessor identifiers as parameters.
They shouldn't be baked into the body of the lambda because then the __func__ will reflect the lambda rather than the routine invoking the lambda.
#include <sstream>
#define FUNC_LOCATION \
[](auto fn, auto ln) { \
std::stringstream ss;
ss << fn << ":" << ln << " "; \
return ss.str(); \
}(__func__, __LINE__)
int main() {
std::cout << FILE_LOCATION << "is <file_name>:<line_number>" << std::endl;
return 0;
}
This question already has answers here:
How do I temporarily disable a macro expansion in C/C++?
(6 answers)
Closed 5 years ago.
The goal here is to simply get a, b, c out instead of their actual values. The setup is "simple enough":
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <iostream>
// Define "invalid" sequence first
#define SEQ (a)(b)(c)
// Try to create "final" value with `std::string("elem")`
// Brought in for explicit `std::string`, but no dice
#define MAKE_XSTRING(x) MAKE_STRING(x)
#define MAKE_STRING(x) std::string(#x)
// oh, the humanity! vvvvvvvvvvvv or BOOST_PP_STRINGIZE
#define HUMANIZE(r, data, elem) (MAKE_XSTRING(elem))
#define SEQ_HUMAN BOOST_PP_SEQ_FOR_EACH(HUMANIZE,,SEQ)
So what I'm expecting at this point is what I have: a new sequence with (std::string("a")) etc:
// confirmation: vvvvvvvvvvvvvvvv
// warning: Humans: (std::string("a")) (std::string("b")) (std::string("c"))
#pragma message "Humans: " BOOST_PP_STRINGIZE(SEQ_HUMAN)
Thinking I'm so very clever and have gotten my values sorted out in some explicit strings, now I define the actual values for what the "real" code needs.
// Now that we have the "final" values, actually define the real values
// in real code, it's some lengthy nested namespaces (inconvenient to type)
#define a 123
#define b 456
#define c 789
And at long last, lets print them to make sure they aren't expanded:
// Let there be printing!
#define GOTTA_PRINT_EM_ALL(r,data,i,elem) << ((i)+1) << ". " << elem << std::endl
int main(int argc, const char **argv) {
std::cout << "Humans: " << std::endl
BOOST_PP_SEQ_FOR_EACH_I(GOTTA_PRINT_EM_ALL,,SEQ_HUMAN);
}
But it seems the aliens did indeed take over:
Humans:
1. 123
2. 456
3. 789
Given that they're supposed to be std::string("a")...how the heck are the real values getting back in there?! I thought maybe the ("a") from the std::string constructor was creating issues, but it doesn't seem so (BOOST_PP_STRINGIZE results in same behavior). Any suggestions?
The macro indeed expands into code tokens:
test.cpp|24 col 1| note: #pragma message: Humans: (std::string("123")) (std::string("456")) (std::string("789"))
Now when you insert the code tokens into your GOTTA_PRINT_EM_ALL macro, you get
<< ((0)+1) << ". " << std::string(\"123\") << std::endl << ((1)+1) << ". " << std::string(\"456\") << std::endl << ((2)+1) << ". << std::string(\"789\")" << std::endl
Completely expectedly printing
Humans:
1. 123
2. 456
3. 789
To get the "code tokens" you need to stringize them as well:
// Let there be printing!
#define GOTTA_PRINT_EM_ALL(r,data,i,elem) << ((i)+1) << ". " << BOOST_PP_STRINGIZE(elem) << std::endl
Printing
Humans:
1. std::string("123")
2. std::string("456")
3. std::string("789")
See it Live On Coliru
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <iostream>
#include <string>
#define a 123
#define b 456
#define c 789
#define SEQ (a)(b)(c)
// Try to create "final" value with `std::string("elem")`
// Brought in for explicit `std::string`, but no dice
#define MAKE_STRING(x) std::string(#x)
#define MAKE_XSTRING(x) MAKE_STRING(x)
#define HUMANIZE(r, data, elem) (MAKE_XSTRING(elem))
#define SEQ_HUMAN BOOST_PP_SEQ_FOR_EACH(HUMANIZE,,SEQ)
// Let there be printing!
#define GOTTA_PRINT_EM_ALL(r,data,i,elem) << ((i)+1) << ". " << BOOST_PP_STRINGIZE(elem) << std::endl
int main() {
std::cout << "Humans: " << std::endl
BOOST_PP_SEQ_FOR_EACH_I(GOTTA_PRINT_EM_ALL,,SEQ_HUMAN);
}
Some time ago, I made this beautiful assert macro for c and c++ programs
#define ASSERT(truthy, message) \
if (!(truthy)) \
{\
cout << message << " on line " << __LINE__ << " in file " << __FILE__ << ". Check was " << #truthy << endl;\
}
Scatter ASSERT calls throughout your code, and it will warn you whenever the truthy value is not truthy! Very handy during development to remind you of potential mistakes.
ex
ASSERT(filesFound > 0, "Couldn't find any files, check your path!");
When filesFound is 0, the macro will print out
Couldn't find any files, check your path! on line 27 in file
openFiles.c. Check was filesFound > 0
Now what I want it to print, to give me even more relevant information, is the value of any variables passed into the truthy parameter. Like this
Couldn't find any files, check your path! on line 27 in file
openFiles.c. Check was filesFound > 0, filesFound is 0
This seems lisp-like territory, I wonder, is there any black magic c preprocessing that I can use to evaluate variables and functions to their values, without evaluating the truthy statement?
I assume to be disappointed.
An alternative solution which I've always used is to support varargs in the macro and then force the assert user to specify the relevant message / variables - it's a little bit of extra work each time, but on the plus side you can get exactly the formatting that you want and include information not available in the "truthy" bit, e.g:
#define ASSERT(truthy, message, ...) \
if (!(truthy)) \
{\
MyAssertHandler(__LINE__, __FILE__, #truthy, message, ##__VA_ARGS__);
}
Then you're handler is just a fairly standard var-arg function that can use e.g. vsnprintf to generate the message and output it, e.g. off the top of my head:
void MyAssertHandler(int line, const char* file, const char* expressionStr, const char* format, ...)
{
// Note: You probably want to use vsnprintf instead to first generate
// the message and then add extra info (line, filename, etc.) to
// the actual output
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
// Log to bug database, DebugBreak() if a debugger is attached, etc.
}
usage:
ASSERT(IsBlah(), "BlahBlah: x = %.2f, name = %s", GetX(), GetName());
I cannot imagine a way to do it... except by passing another parameter
#define ASSERT_PARAM(truthy, message, param) \
if (!(truthy)) \
{\
cout << message << " on line " << __LINE__ << " in file " << __FILE__ << ". Check was " << #truthy << ", value was " << param << endl;\
}
You would use it that way:
ASSERT_PARAM(filesFound > 0, "Couldn't find any files, check your path!", filesFound);
getting:
Couldn't find any files, check your path! on line 27 in file openFiles.c. Check was filesFound > 0, value was 0
What you are trying to do sounds very complicated. I'm afraid in C++ it's not possible.
Technically what you are evaluating is a bool expression so you can pass it to a parser whenever the assertion fails. The parser then will build the expression tree, get the leaves (elements of the expression) and return them. The returned values then should be printed out. To do that you will need support for reflection which is actually not supported in C++ AFAIK.
Maybe not the dream solution, but you can pass whole statements to a macro.
#define ASSERT(trusty, action) if (!trusty) { action }
ASSERT(trusty, cout << a << b;)
ASSERT(trusty, printf("%d, %f\n", a, b);)
I think you can split up the truthy Expression like they do it in the first answer here and then you can probably print the individual values. But I'm not sure if it actually works.
The printing could then be resulved using a variadic template function
Perhaps you could compromise and only allow 2 variables and 1 operator in the assertion expression? If so, you could make an ad hoc solution like this:
#include <iostream>
#include <string>
#define STRINGIFY(x) #x
#define BIN_ASSERT(obj1, op, obj2, msg) \
if(!(obj1 op obj2)) \
{ \
std::cout << msg << " on line " << __LINE__ \
<< " in file " << __FILE__ \
<< "." << std::endl \
<< "Check was " \
<< STRINGIFY(obj1) STRINGIFY(op) STRINGIFY(obj2) \
<< "." << std::endl \
<< "Operator " << #obj1 << ": " << obj1 \
<< "." << std::endl \
<< "Operator " << #obj2 << ": " << obj2 \
<< "." << std::endl; \
}
int main (void)
{
int x = 2;
int y = 3;
std::string s1 = "hello";
std::string s2 = "world";
BIN_ASSERT(1, +, -1, "Value zero"); std::cout << std::endl;
BIN_ASSERT(x, ==, y, "Numbers not equal"); std::cout << std::endl;
BIN_ASSERT(s1, ==, s2, "Strings not equal"); std::cout << std::endl;
}
Output:
Value zero on line 30 in file test.c.
Check was 1+-1.
Operator 1: 1.
Operator -1: -1.
Numbers not equal on line 31 in file test.c.
Check was x==y.
Operator x: 2.
Operator y: 3.
Strings not equal on line 32 in file test.c.
Check was s1==s2.
Operator s1: hello.
Operator s2: world.
I wonder if having the macro take a message is really that useful. A failed assertion is a message to the developer that there is a bug in the code that caused an exceptional behaviour or put the program in an unacceptable state. The user has less to do with it (if they even have access to the source code).
The code below defines an ASSERT macro that takes a boolean expression, evaluates it and prints an informational message. The message contains a value that you've asked to inspect upon failing the assertion.
The macro, just like the standard assert() macro (in <cassert>) goes on to call abort() (from <cstdlib>) to cause an abnormal program termination. This is what you want, because the program entered a state in which it didn't know what more to do.
I'm using std::printf() here for brevity. You do whatever you want.
#include <cstdlib>
#include <cstdio>
#define ASSERT(value, inspect) \
if (!(value)) { \
std::printf("ASSERTION FAILED: '%s', %s is %d: %s#%s:%d\n", #value, \
#inspect, inspect, __func__, __FILE__, __LINE__); \
abort(); \
}
int foo() { return 42; }
int main()
{
// ...
ASSERT(foo() - 40 == 1, foo());
//...
}
Program run:
$ ./a.out
ASSERTION FAILED: 'foo() - 40 == 1', foo() is 42: main#prog.cc:16
Abort
It's not possible to do exactly what you ask for without adding more parameters to the macro. At some point you'll have to stop and realize that you're spending time on creating a text string that you do not want to see.
You need to build an expression 'grabber' / builder.
The macro would become something like:
#define ASSERT_PARAM(truthy, message, param) \
if (!(truthy)) \
{\
Grabber g;
g << #truthy; // grab expression as string
g % truthy; // grab expression and values
cout << message << " on line " << __LINE__ << " in file " << __FILE__ << ". Check was " << #truthy << ", value was " << param << endl;\
cout << g; \
}
What does Grabber do?
It is a bunch of crazy C++ that builds up an expression. It would overload every operator to 'grab' the params of the operator. Every operator returns a reference to the grabber, so it can grab the next operator. ie
Grabber g;
g % filesFound > 0;
Since % (and * and /) have high precedence, the above parses like:
((g % filesFound) > 0)
If template<typename T> Grabber::operator%(T const & val) just records (or prints) the value passed in (ie filesFound), and - importantly - returns itself (g) so that it becomes part of the next expression: ie it becomes g > 0. Causing template<typename T> Grabber::operator>(T const & val) to be called, and > 0 to be recorded.
Then cout << g can spew out everything grabbed.
As mentioned above "It is possible — the Catch library does it. But it’s hellishly difficult".
P.S. you should wrap your macro in a do ... while 0 like this:
#define ASSERT_PARAM(truthy, message, param) \
do \
{ \
if (!(truthy)) \
{\
cout << message << " on line " << __LINE__ << " in file " << __FILE__ << ". Check was " << #truthy << ", value was " << param << endl;\
cout << g; \
} \
} while (0)
What you have currently means that this is valid code:
ASSERT(foo != 0)
else
{
}
And this is NOT valid code:
if (foo != nullptr)
ASSERT(foo->bar != nullptr);
else
x = 10;
Surprisingly, I solved a similar problem before, but I'm not sure if it could help you in this case.
The original solution was proposed by Andrei Alexandrescu in the article Enhancing Assertions, and with no question, relying on some macro tricks.
This amazing facility can be used as the following:
string s1, s2;
...
SMART_ASSERT(s1.empty() && s2.empty())(s1)(s2);
And if something goes wrong, the message would be displayed
Assertion failed in matrix.cpp: 879412:
Expression: 's1.empty() && s2.empty()'
Values: s1 = "Wake up, Neo"
s2 = "It's time to reload."
Be noted that, the SMART_ASSERT can capture infinite variables, theoretically.
For implementation details, please check out the article.
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.