sharkdp / dbg-macro

A dbg(…) macro for C++
MIT License
2.97k stars 257 forks source link

Allow specifying the output stream #105

Open alexeyr opened 3 years ago

alexeyr commented 3 years ago

When using RapidCheck, I'd like the option to write to RC_LOG() instead of std::cerr:

Since the property function may be called many times, using classic debugging techniques such as printing to stdout or stderr can prove confusing. The RC_LOG macro provides a better way to log information during the execution of a test case. Information logged this way will only be printed on failure after the minimal test case has been found.

DerekCresswell commented 3 years ago

This likely wouldn't be too hard. We could just add #define DBG_OUTPUT std::cerr and then users could override it.

alexeyr commented 3 years ago

Will you make this change or should I make a PR?

DerekCresswell commented 3 years ago

By all means, be my guest. We'd need that definition, with cerr as the default, and to add that information to the readme. As well we'd need a test case for this. I'll certainly review a PR if you make it.

I might mention, in the past the owner of this repo has expressed that they want as few as possible compile time options so it's possible they may reject this change. But seeing as it's fairly simple, it might not be a big issue.

sharkdp commented 3 years ago

Indeed - I'd prefer a non-preprocessor way to make this work. Maybe this could be an argument to dbg::DebugOutput or to .print(…). This way, we would have

#define dbg(...)                                    \
  dbg::DebugOutput(__FILE__, __LINE__, __func__)    \
      .print(std::cerr, {DBG_MAP(DBG_STRINGIFY, __VA_ARGS__)}, \
             {DBG_MAP(DBG_TYPE_NAME, __VA_ARGS__)}, __VA_ARGS__)

as the default, but users could define their own

#define my_dbg(...)                                    \
  dbg::DebugOutput(__FILE__, __LINE__, __func__)    \
      .print(my_stream, {DBG_MAP(DBG_STRINGIFY, __VA_ARGS__)}, \
             {DBG_MAP(DBG_TYPE_NAME, __VA_ARGS__)}, __VA_ARGS__)

Note: I haven't thought about this in detail. That approach might not work.

alexeyr commented 3 years ago

What about a variant of dbg like

#define dbg_to(stream, ...)                                    \
  dbg::DebugOutput(__FILE__, __LINE__, __func__)    \
      .print(stream, {DBG_MAP(DBG_STRINGIFY, __VA_ARGS__)}, \
             {DBG_MAP(DBG_TYPE_NAME, __VA_ARGS__)}, __VA_ARGS__)

#define dbg(...) dbg_to(std::cerr, __VA_ARGS__)

and then

#define my_dbg(...) dbg_to(my_stream, __VA_ARGS__)

? It's still a preprocessor solution but less "magical", not a compile-time option, and the users don't need to know internal details (I also haven't yet checked if this works).

sharkdp commented 3 years ago

@alexeyr I like that :+1:

alexeyr commented 3 years ago

Then I'll try to make a PR when I have free time.

thecaralice commented 3 years ago

What about output coloring? When should it be enabled? For example, cout would have it enabled if stdout is a tty and an ofstream would have it disabled. Is it possible to cover all cases?

sharkdp commented 3 years ago

Good question. Maybe dbg_to should take a third (enum or bool) parameter that enables/disables colors.