Блог пользователя Qualified

Автор Qualified, история, 4 года назад, По-английски

My debugging template is:

#define ts to_string
string ts(char c) { return string(1, c); }
string ts(bool b) { return b ? "true" : "false"; }
string ts(const char* s) { return (string)s; }
string ts(string s) { return s; }
template<class A> string ts(complex<A> c) { 
	stringstream ss; ss << c; return ss.str(); }
string ts(vector<bool> v) { 
	string res = "{"; for(int i = 0; i < si(v); ++i) res += char('0' + v[i]);
	res += "}"; return res; }
template<size_t SZ> string ts(bitset<SZ> b) {
	string res = ""; for(int i = 0; i < SZ; ++i) res += char('0' + b[i]);
	return res; }
template<class A, class B> string ts(pair<A,B> p);
template<class T> string ts(T v) {
	bool fst = 1; string res = "{";
	for (const auto& x: v) {
		if (!fst) res += ", ";
		fst = 0; res += ts(x);
	}
	res += "}"; return res;
}
template<class A, class B> string ts(pair<A,B> p) {
	return "(" + ts(p.f) + ", " + ts(p.s) + ")"; }

void DBG() { cerr << "]" << endl; }
template<class H, class... T> void DBG(H h, T... t) {
	cerr << ts(h); if (sizeof...(t)) cerr << ", ";
	DBG(t...); }
#ifdef LOCAL
#define dbg(...) cerr << "[" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__)
#else
#define dbg(...) 0
#endif

When I type

dbg(a, n)

where 'a' is the vector name and n is the size of the vector. 'a' contains the following {1, 2, 3, 4, 5} and n = 5

it prints

[a, n]: [{1, 2, 3, 4, 5}, 5]

but I want it to print

[a]: [{1, 2, 3, 4, 5}]
[n]: [5]

without having to type

dbg(a);
dbg(n);

Is there any way to do this?

  • Проголосовать: нравится
  • +3
  • Проголосовать: не нравится

»
4 года назад, # |
Rev. 5   Проголосовать: нравится 0 Проголосовать: не нравится

Here is code that does what you want. DBG takes a string with the names separated by commas as the first parameter, and the variables as the remaining parameters. Then it prints the first name and the first variables, and passes the rest recursively to DBG.

void DBG(string names) {}
template<class H, class... T> void DBG(string names, H h, T... t) {
	auto pos = names.find(',');
	auto first_name = names.substr(0, pos);
	auto rest = names.substr(pos+1);
	// Strip space at the beginning
	while(rest.front() == ' '){
		rest = rest.substr(1);
	}
	cerr << "["<<first_name<<"] ["<<ts(h)<<"]"<<endl;
	DBG(rest, t...);
}
#ifdef LOCAL
#define dbg(...) DBG(#__VA_ARGS__, __VA_ARGS__)
#else
#define dbg(...) 0
#endif
  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    What am I supposed to put in the function DBG?

    • »
      »
      »
      4 года назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      DBG takes the comma separated names of the variables, and then the variables as parameters.

      You just need to replace this part of your code with the code I gave.

      • »
        »
        »
        »
        4 года назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Thanks! This is the new code that I am working with:

        Code

        dbg converts dbg(a, n); to dbg(a); dbg(n); edbg doesn't change dbg(a, n)

»
4 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

I use the following macros if need debugging:

#define INFO1(x)                #x << ": " << (x)
#define INFO2(x, ...)           INFO1(x) << ", " << INFO1(__VA_ARGS__)
#define INFO3(x, ...)           INFO1(x) << ", " << INFO2(__VA_ARGS__)
#define INFO4(x, ...)           INFO1(x) << ", " << INFO3(__VA_ARGS__)

#define SELECT(_1, _2, _3, _4, X, ...)  X

#define DUMP(...)               SELECT(__VA_ARGS__, INFO4, INFO3, INFO2, INFO1)(__VA_ARGS__)
#define TRACE(...)              do { std::clog << DUMP(__VA_ARGS__) << '\n'; } while (false)

Sample usage:

int x = -1, y =  2, z = -3;
TRACE(x, y, z);

Output: x: -1, y: 2, z: -3

All you need is to overload the stream output operators for vector<>, pair<>, etc. as you want to.