How to concat __func__ and __LINE__ in a macro definition - c++

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;
}

Related

Using BOOST_PP_SEQ_FOREACH_R to recursively process enums

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.

Concat for predefined macros

I would like to make single string from __FILE__, __FUNCTION__, and __LINE__ predefined macros.
#define LOG_LINE __FILE__ " " __FUNCTION__ " " __LINE__
This probably will don't work because compiler concat don't work with integers which __LINE__ is.
#define LOG_LINE __FILE__ __FUNCTION__
also don't work, because:
error: expected ';' before '__FUNCTION__'
How to achieve that to have
std::cout << LOG_LINE which will expand to e.g. main.cpp main 8?
Solution:
#define LOG_LINE __FILE__ << " " << __FUNCTION__ does not satisfy me because sometimes I would like to use it as string (big macro with sstream also is not valid solution ;).
You may use the following:
#define LOG_LINE (std::string(__FILE__ " ") + __FUNCTION__ + " " + std::to_string(__LINE__))
Live example

VC++ marco, getting raw text of parameter

How do I get the text of the data given to value, not the value of the executed expression?
#define PRINT_VALUE(value) std::cout << "Value " << __RAWTEXT(value) << " is " << value << "\n";
__RAWTEXT is something I made up. Is there really something out there that does this though?
int testVariable = 5;
PRINT_VALUE(testVariable);
The output of this should be
Value testVariable is 5
Use the "stringize" operator # for this:
#define PRINT_VALUE(value) std::cout << "Value " << #value << " is " << value << "\n";
It's pretty straightforward, #TTT in a macro converts TTT to "TTT", a string literal.
It's worth mentioning that when the parameter is itself a macro, you'll get the name of the macro. However, if the parameter is passed to a subsequent macro, it's "unpacked". So you see these sometimes:
#define STRINGIZE2(X) #X
#define STRINGIZE(X) STRINGIZE2(X)
Here they are in action:
#define TEST Bob
std::cout << #TEST; //results in "TEST"
std::cout << STRINGIZE2(TEST); //results in "TEST"
std::cout << STRINGIZE(TEST); //results in "Bob"
Not relevent to your question but also notable is the "concat" macro operator ## which "glues" two bits of text togeather. std::st ## ing results in std::string. Useful in macros:
#define make_thing(X) \
structX##_class {
static const char* const name=#X;
};
make_thing(Foo);
std::cout << Foo_class::name;
And again, if a parameter is a macro, you get the macro name. So here's the de-macro macros:
#define GLUE2(X,Y) (X##Y)
#define GLUE(X,Y) GLUE2(X,Y)
#define HEY "HELLO"
#define THERE "WORLD"
std::cout << GLUE(HEY,THERE); //"HELLOWORLD"

C++ macro with variable arguments

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() )

Make a C++ macro that acts like a stream

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.