Please subscribe to the official Codeforces channel in Telegram via the link https://t.me/codeforces_official. ×

rachitiitr's blog

By rachitiitr, 6 months ago, In English

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

 
 
 
 
  • Vote: I like it
  • +139
  • Vote: I do not like it

»
6 months ago, # |
  Vote: I like it 0 Vote: I do not like it

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

  • »
    »
    6 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

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

»
6 months ago, # |
  Vote: I like it +11 Vote: I do not like it

I use something like this

#define gg(...) [](const auto&...x){ char c='='; cerr<<#__VA_ARGS__<<" "; ((cerr<<exchange(c,',')<<" "<<x),...); cerr<<endl; }(__VA_ARGS__);

usage the same

»
6 months ago, # |
  Vote: I like it +8 Vote: I do not like it

I simply straight up copied tourist's debugging template

»
6 months ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like it

Thanks but you still have to comment it out before submitting. Maybe use cerr ?

  • »
    »
    6 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    what is the benefit to use cerr?

    • »
      »
      »
      6 months ago, # ^ |
        Vote: I like it +4 Vote: I do not like it

      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.

»
6 months ago, # |
Rev. 3   Vote: I like it +18 Vote: I do not like it

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.hpp

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

Results:

output

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

  • »
    »
    6 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

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

    • »
      »
      »
      6 months ago, # ^ |
        Vote: I like it +1 Vote: I do not like it

      "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
      • »
        »
        »
        »
        6 months ago, # ^ |
          Vote: I like it 0 Vote: I do not like it

        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?

        • »
          »
          »
          »
          »
          6 months ago, # ^ |
          Rev. 2   Vote: I like it 0 Vote: I do not like it

          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.

  • »
    »
    6 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    please add using namespace std in the first line of your myprettyprint.hpp

    I don't know if or how it's working for you without std. I had to include it.

»
6 months ago, # |
Rev. 2   Vote: I like it +3 Vote: I do not like it

I simply use one existing pretty print header file

Update: put this in your stdc++.h

#ifdef LOCAL
#include<pprint.hpp>
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
  • »
    »
    6 months ago, # ^ |
    Rev. 2   Vote: I like it +1 Vote: I do not like it

    I tried to compile and it threw several errors. Am I missing something?
    [edit] fixed : I was not using c++17

»
6 months ago, # |
  Vote: I like it 0 Vote: I do not like it

use fmtlib and wait for C++20

#include "fmt/core.h"

fmt::print("x={} y={} z={}\n", x, y, z);
»
6 months ago, # |
  Vote: I like it 0 Vote: I do not like it

This is what I use, It looks pretty lengthy and ugly but works like a charm for me.

Debug Template
»
6 months ago, # |
Rev. 3   Vote: I like it +8 Vote: I do not like it

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

Note: This would work only with C++17 and later (because of std::apply and if constexpr among others).

Some advantages:

  1. 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<pair<string, vector<tuple<int, char>>>> with this template too.

  2. 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

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!

»
6 months ago, # |
  Vote: I like it +3 Vote: I do not like it

May you suggest other resources for further reading regarding variadic macros and fold expressions. Thanks !

»
6 months ago, # |
  Vote: I like it +5 Vote: I do not like it

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!

»
6 months ago, # |
  Vote: I like it +3 Vote: I do not like it

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.