Hi everyone.
This is my template for debugging in C++. I was inspired by Tourist's source code and modified it to my style. Here is it:
To debug, just type: debug(x, y, z...)
. It requires C++ 11 or above.
It can work with:
Primitive data types:
bool
,int
,long long
,float
, ...std::pair
,std::string
- Collection types:
std::vector
,std::map
,std::set
, ... - Expressions
It also support multiple arguments.
How to use
Primitive data types:
bool a = true;
debug(a);
int b = 1;
float c = 2.5;
long long d = LLONG_MAX;
char e = 'e';
debug(a, b, c, d, e);
Output:
'[a] = [true]'
'[a, b, c, d, e] = [true, 1, 2.5, 9223372036854775807, 'e']'
std::pair
and std::string
:
pair<int, int> a = {1, 2};
pair<string, bool> b = {"abcd", false};
pair<char, float> c = {'x', 0.5};
string d = "This is a string";
pair<int, pair<int, int> > e = {1, {2, 3}};
debug(a, b, c, d, e);
Output:
'[a, b, c, d, e] = [{1, 2}, {"abcd", false}, {'x', 0.5}, "This is a string", {1, {2, 3}}]'
Note: You should only debug a pair of simple data types. For example, the debug won't work if one of pair's elements is collection type (std::vector
, std::map
, std::set
...).
Collection types:
Basically, the debug works with collections types which you can iterate by for (auto i: a)
. So the debugger won't work with collection types like std::queue
or std::stack
.
vector<int> a = {1, 2, 3, 4};
set<int> b = {1, 2, 2, 3, 3, 4, 4, 5};
map<string, int> c;
c["string 1"] = 1;
c["string 2"] = 2;
debug(a, b, c);
unordered_map<string, int> d;
d["string 3"] = 3;
d["string 4"] = 4;
multiset<int> e = {5, 5, 4, 3, 1, 1, 2};
vector<vector<int> > f = {{1, 2, 3}};
debug(d, e, f);
Output:
'[a, b, c] = [{1, 2, 3, 4}, {1, 2, 3, 4, 5}, {{"string 1", 1}, {"string 2", 2}}]'
'[d, e, f] = [{{"string 4", 4}, {"string 3", 3}}, {1, 1, 2, 3, 4, 5, 5}, {{1, 2, 3}}]'
Note: I haven't tried the debug with other complex data types nested in collection types.
Expressions:
int a = 1;
int b = 2;
debug(a + b, a * b, a / b, a - b, a / (float)b, 2019, 2019 - 1);
Output:
'[a + b, a * b, a / b, a - b, a / (float)b, 2019, 2019 - 1] = [3, 2, 0, -1, 0.5, 2019, 2018]'
You can use the template and change it's style to what you want. Hope it would help you debug in C++ easier.
You could
void __print(int x) {cerr << x;}
void __print(long x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(unsigned x) {cerr << x;}
void __print(unsigned long x) {cerr << x;}
void __print(unsigned long long x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << ''' << x << ''';}
void __print(const char *x) {cerr << '"' << x << '"';}
void __print(const string &x) {cerr << '"' << x << '"';}
void __print(auto x) {cerr << x;}
If we do it, the marcro to work with collection types won't work
You're right. I'm sorry
No problem dude. Those lines are actually not so nice
Auto comment: topic has been updated by tantam75 (previous revision, new revision, compare).
Have you compared it with this template for debugging which is also based on a submission by tourist? If yes, then how does it compare?
Also, how is your template better than what tourist used?
I can see how it is worse: in your
#define
it would be better to use a comma instead of a semicolon so that it is treated as one statement if it is not enclosed in braces for example as the body of afor
loop.Does not work for vector :( And of course for arrays
amazing, i just learn c++ template, and then i find these good stuffs.
.
You can use snippets in vs code for this purpose... You can find this in settings gear icon...
Doesn't work with arrays. How can I modify it to work with arrays?
The function template
template <typename T, typename... V> void _print(T t, V... v)
takes its arguments by value. Arrays cannot be copied and are instead treated as pointers. Pointers don't know the size of the underlying array and thus do not supportstd::begin
andstd::end
. Range-based for-loops, however, require these two functions.To prevent the decay,
_print
should take its arguments by reference. You can either use lvalue references_print(T const& t, V const&... v)
, or forwarding references_print(T&& t, V&&... v)
. The latter is usually preferred, but here it doesn't make a difference. In both cases, you avoid the costly copying in the recursion.The same thing can be achieved by overloading ostream for STL containers (this way nested structures work too). Also, you can come up with some pretty neat one liners using fold expressions and lambdas.
If you'd like a more generic reader-writer/debugger template (using SFINAE) for C++ STL, you can look at submissions by @Narut on CF.
This is super helpful Thanks! But can you tell me how to redirect the cerr output to a file.. I do it with the command freopen("error.txt", "w", stdout ) but for multiple variables, it's showing the output on the terminal
freopen("error.txt", "w", stderr);
cin — stdin
cerr — stderr
cout — stdout
run this in terminal:
./a.out > output.txt 2>error_stream.txt
This will write standard output (from cout) to output.txt and error output (from cerr and clog) to error_stream.txt. Nothing will be printed on terminal. Here "a.out" is the binary/compiled programme. If you have changed that name then change the above command accordingly.This is my template and debug will work for any complex structure.
This is very useful debugging template.
it works for every builtin fuction and stl well.