diff --git a/dbg.h b/dbg.h index 891638c..84239a6 100644 --- a/dbg.h +++ b/dbg.h @@ -163,26 +163,17 @@ prettyPrint(std::ostream &stream, Container const &value) { return true; } -template -class DebugOutput_impl { +class DebugOutput { public: - DebugOutput_impl(const char* filename, int line, const char* function_name, Args && ... args) + DebugOutput(const char* filename, int line, const char* function_name, const char* argument) : m_stderr_is_a_tty(isatty(fileno(stderr))), m_filename(filename), m_line(line), m_function_name(function_name), - m_arguments{args...} {} - - template - void print(Brgs&&... brgs) { - size_t i = 0; - // expander trick to emulate C++17 fold expression - using expander = int[]; - (void)expander{0, (void(printValue(std::forward(brgs), i++)), 0)...}; - } + m_argument(argument) {} template - void printValue(T&& value, size_t i) const { + T&& print(T&& value) const { const T& ref = value; std::stringstream stream_value; const bool print_expression = prettyPrint(stream_value, ref); @@ -190,10 +181,12 @@ class DebugOutput_impl { std::cerr << ansi(ANSI_WARNING_COLOR) << "[DEBUG " << m_filename << ":" << m_line << " (" << m_function_name << ")] "; if (print_expression) { - std::cerr << ansi(ANSI_RESET) << m_arguments[i] << ansi(ANSI_BOLD) << " = "; + std::cerr << ansi(ANSI_RESET) << m_argument << ansi(ANSI_BOLD) << " = "; } std::cerr << ansi(ANSI_RESET) << ansi(ANSI_VALUE_COLOR) << stream_value.str() << ansi(ANSI_RESET) << std::endl; + + return std::forward(value); } private: @@ -210,7 +203,7 @@ class DebugOutput_impl { const std::string m_filename; const int m_line; const std::string m_function_name; - const char * m_arguments[sizeof...(Args)]; + const std::string m_argument; static constexpr const char* const ANSI_EMPTY = ""; static constexpr const char* const ANSI_WARNING_COLOR = "\x1b[33;01m"; @@ -219,46 +212,10 @@ class DebugOutput_impl { static constexpr const char* const ANSI_RESET = "\x1b[0m"; }; -template -DebugOutput_impl DebugOutput(const char* filename, - int line, - const char* function_name, - Args&&... args) { - return DebugOutput_impl{filename, line, function_name, - std::forward(args)...}; -} - } // namespace dbg_macro -#define STRINGIFY(s) _STRINGIFY(s) -#define _STRINGIFY(s) #s - -#define FOREACH_1(fn, x) fn(x) -#define FOREACH_2(fn, x, ...) fn(x), FOREACH_1(fn, __VA_ARGS__) -#define FOREACH_3(fn, x, ...) fn(x), FOREACH_2(fn, __VA_ARGS__) -#define FOREACH_4(fn, x, ...) fn(x), FOREACH_3(fn, __VA_ARGS__) -#define FOREACH_5(fn, x, ...) fn(x), FOREACH_4(fn, __VA_ARGS__) -#define FOREACH_6(fn, x, ...) fn(x), FOREACH_5(fn, __VA_ARGS__) -#define FOREACH_7(fn, x, ...) fn(x), FOREACH_6(fn, __VA_ARGS__) - -#define FOREACH_N(_1, _2, _3, _4, _5, _6, _7, N, ...) N - -// clang-format off -#define FOREACH(fn, ...) \ - FOREACH_N(__VA_ARGS__, \ - FOREACH_7, \ - FOREACH_6, \ - FOREACH_5, \ - FOREACH_4, \ - FOREACH_3, \ - FOREACH_2, \ - FOREACH_1) \ - (fn, __VA_ARGS__) -// clang-format on - -#define dbg(...) \ - dbg_macro::DebugOutput(__FILE__, __LINE__, __func__, \ - FOREACH(STRINGIFY, __VA_ARGS__)) \ - .print(__VA_ARGS__) +// We use a variadic macro to support commas inside expressions (e.g. initializer lists): +#define dbg(...) \ + dbg_macro::DebugOutput(__FILE__, __LINE__, __func__, #__VA_ARGS__).print((__VA_ARGS__)) #endif // DBG_MACRO_DBG_H