c++ - How to enhance this variable-dumping debug macro to be variadic? -
first working code:
#include <iostream> // note: requires compiler has __pretty_function__, gcc or clang #define dump(v) std::cerr << __pretty_function__ << ':' << __line__ << ':' << #v << "='" << (v) << "'\n" int main(int argc) { dump(argc); dump(argc+1); return 0; }
which gives stderr output (gcc):
int main(int):8:argc='1' int main(int):9:argc+1='2'
now i'd have variadic macro number of arguments, example
dump(argc, argc+1);
work, output like:
int main(int):8:argc='1',argc+1='2'
but not yet come nice solution. possible macro? if not, how templates, or combination of macros , templates? c++11 , boost ok if needed, , solution can gcc-specific if there's no standard way. looking actual code, makes variadic dump work described above, or @ least show equivalent info.
ok. not nice. works, prespecified number of arguments (i got lazy @ 4). heavily ripped off here (seriously, click , upvote). uses trick of literally expanding arguments in front of prewritten list, pulling off correct number fixed position @ back. calls correct macro name appending number. clear? nope! here's code:
#include <iostream> // pretty normal macro tricks #define stringize(a) stringize1(a) #define stringize1(a) stringize2(a) #define stringize2(a) #a #define concat(a, b) concat1(a, b) #define concat1(a, b) concat2(a, b) #define concat2(a, b) a##b // faux-recursively dump arguments #define dump_1(first) std::cout << stringize(first) << "='" << first << "'\n"; #define dump_2(first, ...) \ {\ std::cout << stringize(first) << "='" << first << "': ";\ dump_1(__va_args__);\ } while (false) #define dump_3(first, ...) \ {\ std::cout << stringize(first) << "='" << first << "': ";\ dump_2(__va_args__);\ } while (false) #define dump_4(first, ...) \ {\ std::cout << stringize(first) << "='" << first << "': ";\ dump_3(__va_args__);\ } while (false) // count arguments // construct forward/backward list: #define count_args(...) count_args_(__va_args__, rseq()) // forward list on (macro pain): #define count_args_(...) count_args_n(__va_args__) // n+1th element count (predetermined support n) #define count_args_n(_1, _2, _3, _4, n, ...) n #define rseq() 4, 3, 2, 1 // calls correct dump_# #define dump_(n, ...) concat(dump_, n)(__va_args__) // start line, , start "recursion" #define dump(...) \ {\ std::cout << __pretty_function__ << ':' << __line__ << ": "; \ dump_(count_args(__va_args__), __va_args__); \ } while (false) int main(int argc, char* argv[]) { dump(argc); int = 10; const char str[] = "hello, world"; dump(i, str); return 0; }
output:
$ ./a.out int main(int, char**):49: argc='1' int main(int, char**):52: i='10': str='hello, world'
edit: here's simple version of counting part (the hard part):
#include <iostream> #define count_args(...) count_args_(__va_args__, rseq()) #define count_args_(...) count_args_n(__va_args__) #define count_args_n(_1, _2, _3, _4, _5, _6, n, ...) n #define rseq() 6, 5, 4, 3, 2, 1 int main() { std::cout << count_args(a, b) << '\n'; std::cout << count_args(a, b, c, d) << '\n'; return 0; }
output:
1 2
how work?
well set count 6, have. constructs long list, , pulls off 7th element. contains correct value, because list pulls value constructed putting arguments user gave, followed count in reverse.
so adding argument, push backwards count along 1, , higher number it. @ picture:
Comments
Post a Comment