unalive's blog

By unalive, 11 hours ago, In English

I am unfortunately not very good at writing code and can barely function without an easy way to debug said code. I therefore need a debug template at ICPC and spent some time reducing the length of the debug template I use normally. I think it's pretty short already, but it seems like it can be shortened further. I don't know how to do so, hence this blog.

Some considerations:

  1. Can only use features introduced in C++ 17 or earlier, as my region is weird.
  2. Need to be able to debug all STL containers, and any nested versions thereof.

Now, if C++ 20 were allowed, one could simply use the following:

Code

__print() works by repeatedly considering the elements that constitute x and calling __print() on them (whilst ensuring that the output of each __print() call is separated by ,) until << is defined for x by default.

Now, what's the problem with making this code compatible with C++17?

The problem is that there doesn't seem to be a short (in terms of code length) way in C++17 to differentiate between pairs and iterable containers.

I found two solutions, both of which aren't good at all:

1) Use is_literal_type_v to check if T is a pair
Code

This will work if we have pairs like std::pair<int, float> but not with something like std::pair<int, vector<int>>. This is a significant loss of functionality since we now cannot debug things like map<int, vector<int>> which are often used.

2) Just create a separate templated function for pairs
Code

This is also bad because:

  1. Much longer code.
  2. Notice that we now need to use a class/struct/namespace for the two __print() functions as they can call each other.

Can someone help me fix these issues and/or make the code shorter in general? Right now, I think the last one is the best. I can't believe I spent the last 3 hours shortening a piece of code by 5 lines.

For whatever reason, GPT and Claude seems to be unhelpful here. I ran out of access to 4o trying to get it to help me, despite purchasing GPT plus T_T

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

»
11 hours ago, # |
  Vote: I like it 0 Vote: I do not like it

I just realized it cannot debug bitset either QAQ

»
11 hours ago, # |
  Vote: I like it 0 Vote: I do not like it

string to_string(string s) { return '"' + s + '"'; } string to_string(const char* s) { return to_string((string) s); } string to_string(bool b) { return (b ? "true" : "false"); } template <typename A, typename B> string to_string(pair<A, B> p) { return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; } template <typename A> string to_string(A v) { bool first = true; string res = "{"; for (const auto &x : v) { if (!first) { res += ", "; } first = false; res += to_string(x); } res += "}"; return res; } void debug_out() { cerr << endl; } template <typename Head, typename... Tail> void debug_out(Head H, Tail... T) { cerr << " " << to_string(H); debug_out(T...); }
  • »
    »
    11 hours ago, # ^ |
      Vote: I like it +8 Vote: I do not like it
    1. longer
    2. doesn't print argument list
    • »
      »
      »
      11 hours ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      what do you mean by argument list

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

        If you call debug(a, b, c), the template in the blog will output [a, b, c ] = [1, 2, 3]. Your code will just output 1 2 3.

        • »
          »
          »
          »
          »
          10 hours ago, # ^ |
            Vote: I like it 0 Vote: I do not like it

          not really because i use this #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)

»
10 hours ago, # |
  Vote: I like it 0 Vote: I do not like it
»
9 hours ago, # |
  Vote: I like it 0 Vote: I do not like it

Would something like this work? https://godbolt.org/z/fKMjoPhz8