### rachitiitr's blog

By rachitiitr, 3 years ago,

Hi Community,

It's been a while I wrote a blog post here.
You can follow more such tricks on —

## How debug macros work?

Straight to the point, I have often used the debug macro which stringifies the variable names and their values.

#define deb(x) cout << #x << " " << x
int ten = 10;
deb(ten); // prints "ten = 10"


This is often useful in debugging.

## The Problem with this macro — its not scalable

However, when you have multiple variables to log, you end up with more deb2 and deb3 macros.

#define deb(x) cout << #x << " " << x
#define deb2(x) cout << #x << " " << x << " "  << #y << " " << y
#define deb3(x, y, z) cout << #x << " " << x << " "  << #y << " " << y << " "  << #z << " " << z


This is not scalable.

## Solution using a powerful macro

Here is the solution using variadic macros and fold expressions,

#define deb(...) logger(#__VA_ARGS__, __VA_ARGS__)
template<typename ...Args>
void logger(string vars, Args&&... values) {
cout << vars << " = ";
string delim = "";
(..., (cout << delim << values, delim = ", "));
}

int xx = 3, yy = 10, xxyy = 103;
deb(xx); // prints "xx = 3"
deb(xx, yy, xxyy); // prints "xx, yy, xxyy = 3, 10, 103"


Hope this helps, this is going to my template for sure

• +139

| Write comment?
 » 3 years ago, # |   0 Bro, you can overload macro in c++ like this:  __#define GET_MACRO6(_1,_2,_3,_4,_5,_6,NAME,...) NAME__ __define deb_1(a)__ __define deb_2(a,b)__ __define deb_3(a,b,c)__ __define deb_4(a,b,c,d)__ __define deb_5(a,b,c,d,e)__ __define deb_6(a,b,c,d,e,f)__ __define deb(...) GET_MACRO6(__VA_ARGS__,deb_6,deb_5,deb_4,deb_3,deb_2,deb_1)(__VA_ARGS__)__ my full debug code: https://github.com/Wgmlgz/Random-code/blob/main/Cp/template.cpp
•  » » 3 years ago, # ^ |   0 The issue with this is readability. Parameter packs and variadic templates seem like the future and easy to read (when you know how they work).
 » 3 years ago, # |   +11 I use something like this #define gg(...) [](const auto&...x){ char c='='; cerr<<#__VA_ARGS__<<" "; ((cerr<
 » 3 years ago, # |   +8 I simply straight up copied tourist's debugging template
•  » » 3 years ago, # ^ |   0 where can I find it?
 » 3 years ago, # | ← Rev. 2 →   0 Thanks but you still have to comment it out before submitting. Maybe use cerr ?
•  » » 3 years ago, # ^ |   0 what is the benefit to use cerr?
•  » » » 3 years ago, # ^ |   +4 You dont have to comment your debug line during submitting for judging, you can leave there as it is. cerr prints its contents to a separate error log.
•  » » » » 3 years ago, # ^ | ← Rev. 2 →   +17 cerr statements are most likely to cause TLE.so you need to use this macro
 » 3 years ago, # | ← Rev. 3 →   +18 I did some research and searched for very good debugging techniques and templates. So this is what I felt is the best method for debugging, and this works for several stl containers including maps and even policy based data structures. Here is the template: myprettyprint.hpptemplate ostream &operator<<(ostream &os, const pair &p) { return os << '{' << p.first << ", " << p.second << '}'; } template ()))>, class = enable_if_t::value>> ostream &operator<<(ostream &os, const T &c) { os << '['; for (auto it = c.begin(); it != c.end(); ++it) os << &", "[2 * (it == c.begin())] << *it; return os << ']'; } //support up to 5 args #define _NTH_ARG(_1, _2, _3, _4, _5, _6, N, ...) N #define _FE_0(_CALL, ...) #define _FE_1(_CALL, x) _CALL(x) #define _FE_2(_CALL, x, ...) _CALL(x) _FE_1(_CALL, __VA_ARGS__) #define _FE_3(_CALL, x, ...) _CALL(x) _FE_2(_CALL, __VA_ARGS__) #define _FE_4(_CALL, x, ...) _CALL(x) _FE_3(_CALL, __VA_ARGS__) #define _FE_5(_CALL, x, ...) _CALL(x) _FE_4(_CALL, __VA_ARGS__) #define FOR_EACH_MACRO(MACRO, ...) \ _NTH_ARG(dummy, ##__VA_ARGS__, _FE_5, _FE_4, _FE_3, _FE_2, _FE_1, _FE_0) \ (MACRO, ##__VA_ARGS__) //Change output format here #define out(x) #x " = " << x << "; " #define dbg(...) \ cerr << "Line " << __LINE__ << ": " FOR_EACH_MACRO(out, __VA_ARGS__) << "\n" Now, you might be feel that this would make my default template a lot more scary and confusing. So a solution to that is to use the #ifndef ONLINE_JUDGE preprocessor directive, and include the debug template as a .hpp file. main template#pragma GCC target ("avx2") #pragma GCC optimization ("O3") #pragma GCC optimization ("unroll-loops") #include using namespace std; typedef long long ll; #define io ios_base::sync_with_stdio(false);cin.tie(NULL); // ************************DEBUG START******************************** #ifndef ONLINE_JUDGE // if ONLINE_JUDGE is not defined (when compiling on our pc, this is true) //#define cerr cout // if you want to print to stdout, uncomment this #include "myprettyprint.hpp" // include myprettyprint.hpp #else #define dbg(...) // else, when defined (most modern CP sites have this defined), define dbg(...). // this basically just would do nothing on seeing dbg() and thus no need to remove dbg() while submitting. #endif // ************************DEBUG END********************************** ll my_func(ll a, ll b) { return a*b; } void test() { int x=5, y=4; string s="Hello"; vector v={1,2,3,4,5}; set st={34,45}; map > m; for(int i=0;i<3;i++) { for(int j=0;j<4;j++) { m[i].push_back(i+j); } } dbg(x, y, s, v, st); dbg(m, my_func(3,7)); } int main() { io; ll tests=1; //cin>>tests; while(tests--) { test(); } return 0; } Results: outputLine 43: x = 5; y = 4; s = Hello; v = [1, 2, 3, 4, 5]; st = [34, 45]; Line 44: m = [{0, [0, 1, 2, 3]}, {1, [1, 2, 3, 4]}, {2, [2, 3, 4, 5]}]; my_func(3,7) = 21; note: the myprettyprint.hpp should be placed in a directory so that it is in the search path when compiling.in ubuntu, I placed it here: /usr/include/c++/9/myprettyprint.hpp. I hope this helps! original source: link1, link2
•  » » 3 years ago, # ^ |   0 Thanks for this idea! I just want to know that where should I place this hpp file? Inside my compiler's folder (where "bits/stdc++.h" is placed?)
•  » » » 3 years ago, # ^ |   +1 "bits/stdc++.h" if placed under ubuntu (/usr/include/x86_64-linux-gnu/c++/9/bits) and for arch linux (/usr/include/c++/10.2.0/x86_64-pc-linux-gnu/bits).You should put "headerfile.hpp" in the above directory and use it like this code#include #ifndef ONLINE_JUDGE #include #else #define dbg (...) #endif using namespace std; int main() {...your code/template} 
•  » » » » 3 years ago, # ^ |   0 Got it.One doubt though that #define dbg(...) what does this do? Do I need to have some other dbg macro defined above for it to work or is it self sufficient?
•  » » » » » 3 years ago, # ^ | ← Rev. 2 →   0 One doubt though that #define dbg(...) what does this do This will make every dbg(..) statemets an EMPTY line. So, you dont have to comment out every dbg(..) statement in your code before submitting it.✌️ And it is self sufficient.
 » 3 years ago, # | ← Rev. 2 →   +3 I simply use one existing pretty print header fileUpdate: put this in your stdc++.h #ifdef LOCAL #include pprint::PrettyPrinter _printer(std::cerr); #define de(...) _printer.compact(true).print('[', #__VA_ARGS__,"] =", __VA_ARGS__) #define de2(...) _printer.compact(false).print('[', #__VA_ARGS__,"] =", __VA_ARGS__) #endif and put this in your source code: #ifndef LOCAL // https://github.com/p-ranav/pprint #define de(...) #define de2(...) #endif 
•  » » 3 years ago, # ^ | ← Rev. 2 →   +1 I tried to compile and it threw several errors. Am I missing something? fixed : I was not using c++17
 » 3 years ago, # |   0 use fmtlib and wait for C++20 #include "fmt/core.h" fmt::print("x={} y={} z={}\n", x, y, z); 
 » 3 years ago, # |   0 This is what I use, It looks pretty lengthy and ugly but works like a charm for me. Debug Template#ifdef EPSILON #define deb(args...) cerr << "[ " #args << " ] : " , debug(args); #define debx(args...) (Debugger(" ")),args #define debug(args...) (Debugger()) , args class Debugger { public: Debugger(const std::string& _separator = ", ") : first(true), separator(_separator){} template Debugger& operator , (const ObjectType& v) { if(!first) std::cerr << separator; std::cerr << v; first = false; return *this; } ~Debugger() { std::cerr << endl;} private: bool first; std::string separator; }; template inline std::ostream& operator << (std::ostream& os, const std::pair& p) { return os << "(" << p.first << ", " << p.second << ")"; } template inline std::ostream &operator << (std::ostream & os,const std::vector& v) { bool first = true; os << "["; for(unsigned int i = 0; i < v.size(); i++) { if(!first) os << ", "; os << v[i]; first = false; } return os << "]"; } template inline std::ostream &operator << (std::ostream & os,const std::set& v) { bool first = true; os << "["; for (typename std::set::const_iterator ii = v.begin(); ii != v.end(); ++ii) { if(!first) os << ", "; os << *ii; first = false; } return os << "]"; } template inline std::ostream &operator << (std::ostream & os,const std::multiset& v) { bool first = true; os << "["; for (typename std::set::const_iterator ii = v.begin(); ii != v.end(); ++ii) { if(!first) os << ", "; os << *ii; first = false; } return os << "]"; } template inline std::ostream &operator << (std::ostream & os,const std::map& v) { bool first = true; os << "["; for (typename std::map::const_iterator ii = v.begin(); ii != v.end(); ++ii) { if(!first) os << ", "; os << *ii ; first = false; } return os << "]"; } #else #define deb(args...) #define debx(args...) #define debug(args...) #endif 
 » 3 years ago, # | ← Rev. 3 →   +8 I think most of the solutions for debugging here are quite non-generic in nature. I used to have such a debug template too (albeit with variadic macros and lots of overloads for printing STL containers). Then I came across Narut's awesome template for debugging that uses SFINAE in a pretty clever way, and I tinkered with it slightly to make it work with my old pretty printing template, to get the following result: Debugging template#define SFINAE(x, ...) \ template \ struct x : std::false_type {}; \ template \ struct x> : std::true_type {} SFINAE(DefaultIO, decltype(std::cout << std::declval())); SFINAE(IsTuple, typename std::tuple_size::type); SFINAE(Iterable, decltype(std::begin(std::declval()))); template constexpr char Space(const T &) { return (Iterable::value or IsTuple::value) ? '\n' : ' '; } template struct Writer { template void Impl(T const &t) const { if constexpr (DefaultIO::value) os << t; else if constexpr (Iterable::value) { int i = 0; for (auto &&x : t) ((i++) ? (os << Space(x), Impl(x)) : Impl(x)); } else if constexpr (IsTuple::value) std::apply([this](auto const &... args) { int i = 0; (((i++) ? (os << ' ', Impl(args)) : Impl(args)), ...); }, t); else static_assert(IsTuple::value, "No matching type for print"); } template auto &operator()(F const &f, Ts const &... ts) const { return Impl(f), ((os << ' ', Impl(ts)), ...), os << '\n', *this; } }; #ifdef DEBUG #define debug(args...) \ { \ std::string _s = #args; \ std::replace(_s.begin(), _s.end(), ',', ' '); \ std::stringstream _ss(_s); \ std::istream_iterator _it(_ss); \ std::cerr << "Line " << __LINE__ << "\n"; \ err(_it, args); \ } void err(std::istream_iterator it) { std::ignore = it; } template void err(std::istream_iterator it, T a, Args... args) { std::cerr << "\033[0;31m" << *it << " = "; Writer{}(a); std::cerr << "\033[0m"; err(++it, args...); } #define ASSERT(...) \ if (not(__VA_ARGS__)) throw runtime_error(#__VA_ARGS__) #else #define debug(...) 0 #define ASSERT(...) 0 #endif Note: This would work only with C++17 and later (because of std::apply and if constexpr among others).Some advantages: Doing debug(a, b, c) (or any number of parameters) pretty prints variables a, b, c of any sane type defined in the C++ standard or STL (sane as in something that makes sense to be printed). For instance, if it is a pair or an arbitrary tuple of printable types, or a container of printable types, it can be printed using this template, and is hence a printable type. No need to define printing functions for literally every single type. You can print stuff like vector>>> with this template too. It prints the line numbers as well, and takes care of printing containers in separate lines. In terms of formatting, it gives you a nice coloured output too. For those curious, here's the explanation of how it works. Explanation The SFINAE macro uses, very predictably, SFINAE (Substitution Failure Is Not An Error). For those unfamiliar with SFINAE, I'll try to explain it in an intuitive sense without going into too much detail. SFINAE tries to keep compiling when it gets a substitution failure according to the type system, and we can use the order of priority of compilation to our advantage. The usage here tries to perform a certain action and based on whether that action can be compiled or not, it stores the truth value of whether it failed or not in a struct's type (for instance, if T is an integral type, then DefaultIO::value is true, while IsTuple::value is false, and this will be useful when we implement our Writer class which can print everything that we care about. In the Writer class, using this type information, we determine at compile-time which kind of print we want to implement for each class. For a "trivially-printable" type, we can do stuff pretty easily. For a container, we just print everything recursively using our Writer and we win. For a tuple, using std::apply, we can print stuff in the tuple just like what we would do for a container. Now coming to the debugging part, the debug macro takes the arguments, splits them into tokens, prints the line number, and then calls a function that iterates over all the variables and prints them alongside their name using our Writer. And, of course, it's always better to have this all neatly packed into a local header like debug.hpp which helps in keeping your submission clean!
 » 3 years ago, # |   +3 May you suggest other resources for further reading regarding variadic macros and fold expressions. Thanks !
 » 3 years ago, # |   +5 Great article! I'd like to suggest the following: print all variables to stderr to have only solution output in stdout (useful if you're using additional tooling to check your code) run this code only in debug mode (e.g., you can log some expensive function calls) I mostly covered these topics in my article, feel free to check it out!
 » 3 years ago, # |   +3 I am getting the below warning and my code isn't running. warning: fold-expressions only available with '-std=c++17' or '-std=gnu++17' 54 | (..., (cout << delim << values, delim = ", ")); The standard for the CPP set is already c++17 in my vs code.Please help me in setting this debug code as my template.
•  » » 3 years ago, # ^ |   0 Getting same error, have you found a solution yet?
 » 18 months ago, # |   +3 #ifdef LOCAL #include "/Library/debug/debug.h" #define debug(x...) cerr << "[" << #x << "] = ["; _print(x) #else #define debug(x...) #endif I'm putting all my ugly debugging code inside "debug.h" file and include it only if I'm compiling the file locally, and also calling the debug function from an online judge will print nothing.