{"id":15047362,"url":"https://github.com/archibate/debug-hpp","last_synced_at":"2025-10-25T09:32:55.365Z","repository":{"id":238162545,"uuid":"796005357","full_name":"archibate/debug-hpp","owner":"archibate","description":"printing everything including STL containers without pain 🚀","archived":false,"fork":false,"pushed_at":"2024-09-05T17:32:10.000Z","size":224,"stargazers_count":39,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-12T16:41:02.034Z","etag":null,"topics":["cpp","cpp-library","cpp11","debugging","formatting","header-only","single-header-library","utility"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/archibate.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-04T16:44:09.000Z","updated_at":"2024-09-30T09:20:10.000Z","dependencies_parsed_at":"2024-07-24T17:33:11.974Z","dependency_job_id":"574eb5ad-fd39-4504-9c9e-ea309d166a0a","html_url":"https://github.com/archibate/debug-hpp","commit_stats":null,"previous_names":["archibate/debug-hpp"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archibate%2Fdebug-hpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archibate%2Fdebug-hpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archibate%2Fdebug-hpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archibate%2Fdebug-hpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/archibate","download_url":"https://codeload.github.com/archibate/debug-hpp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248138513,"owners_count":21053865,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","cpp-library","cpp11","debugging","formatting","header-only","single-header-library","utility"],"created_at":"2024-09-24T20:57:09.906Z","updated_at":"2025-10-25T09:32:50.326Z","avatar_url":"https://github.com/archibate.png","language":"C++","readme":"# debug.hpp\n\nTired of the dumb debugging of manually traversing containers and `cout \u003c\u003c` them one by one? 🥵\n\nTry this handy header-only library 🚀 prints everything including STL containers without pain! 🤩\n\n[English](README.md) | [简体中文](README.zh_CN.md) | [Download](https://raw.githubusercontent.com/archibate/debug-hpp/main/debug.hpp)\n\n- supports from C++11 to C++23 ✅\n- neat syntax, easy-to-use ✅\n- print almost all STL containers ✅\n- custom class supported ✅\n- automatically disabled in Release build ✅\n- single header only ✅\n- thread safe ✅\n\n## 🎨 Usage\n\n```cpp\ndebug(), \"my variable is\", your_variable;\n```\n\nThe above code prints:\n\n```\nyour_file.cpp:233:  my variable is {1, 2, 3}\n```\n\n\u003e suppose your_variable is an `std::vector`\n\n\u003e [!WARNING]\n\u003e debug() only works in `Debug` build! It is automatically disabled in `Release` build (we do this by checking whether the NDEBUG macro is defined). Yeah, completely no outputs in `Release` build, this is by design.\n\nThis is a feature for convenience: you don't have to busy removing all the debug() sentences after debug done, simply switch to `Release` build and everything debug is gone, no runtime overhead! And when you need debug simply switch back to `Debug` build and everything debug() you written before is back in life.\n\nIf you mean to use debug() even in `Release` build, just `#define DEBUG_LEVEL 1` before including this header file to force enable debugging.\n\n## ✨ Printing custom classes\n\n```cpp\nstruct Student {\n    std::string name;\n    int age;\n\n    // typically we just return a tuple directly, and debug() will dump this class just like a tuple:\n    auto repr() const {\n        return std::make_tuple(name, age);\n    }\n\n    // alternatively, show in a format of {name: \"name\", age: 42}\n    auto repr() const {\n        return std::make_tuple(debug::named_member(\"name\", name), debug::named_member(\"age\", age));\n    }\n\n    // alternatively, let the macro provided by debug.hpp to generate a repr() method for you:\n    DEBUG_REPR(name, age);\n\n    // alternatively return a string directly:\n    std::string repr() const {\n        return \"Student{name: \" + name + \" age: \" + std::to_string(age) + \"}\";\n    }\n\n    // alternatively \u003c\u003c to ostream directly:\n    void repr(std::ostream \u0026os) const {\n        os \u003c\u003c \"Student{name: \" \u003c\u003c name \u003c\u003c \" age: \" \u003c\u003c age \u003c\u003c \"}\";\n    }\n};\n\n// if adding member function is not possible, you may also define repr as free function within the same namespace as Student (thanks to C++'s ADL mechanism):\ninline auto repr(Student const \u0026stu) {\n    return std::make_tuple(name, age);\n}\n\n// global version for the DEBUG_REPR macro for generating repr as free function:\nDEBUG_REPR_GLOBAL(Student, name, age);\n\n// if your class was a template class while you have to define repr as free function...\nDEBUG_REPR_GLOBAL_TEMPLATED(std::pair, (T1, T2), (class T1, class T2), name, age);\n```\n\n\u003e [!WARNING]\n\u003e make sure you have the `const` qualifier! otherwise debug() will refuse to invoke the repr function.\n\n\u003e [!WARNING]\n\u003e For MSVC users: Please turn on `/Zc:preprocessor` before you could the `DEBUG_REPR` macros! This is a famous MSVC bug, not our fault.\n\n## 🎁 Save debug output as string\n\n```cpp\nauto s = static_cast\u003cstd::string\u003e(debug(), \"my variable is\", your_variable);\n// content of `s`: \"your_file.cpp:233:  my variable is {1, 2, 3}\"\n\nauto s = static_cast\u003cstd::string\u003e(debug().noloc(), \"my variable is\", your_variable);\n// content of `s`: \"my variable is {1, 2, 3}\"\n```\n\n## 📝 Redirect debug output to spdlog\n\n```cpp\n#define DEBUG_OUTPUT(x) spdlog::info(x)  // define this macro before including the header to customize where debug() output its result\n#include \"debug.hpp\"\n```\n\n## 🚩 Assertion check\n\n```cpp\ndebug().check(some_variable) \u003e 0;\n```\n\nWill trigger a 'trap' interrupt (__debugbreak for MSVC and __builtin_trap for GCC, configurable, see below) for the debugger to catch when `some_variable \u003e 0` is false, as well as printing human readable error message:\n```\nyour_file.cpp:233:  assertion failed: 3 \u003c 0\n```\n\n\u003e [!TIP]\n\u003e See [test.cpp](test.cpp) for more usage showcases.\n\n## 🌠 Release build\n\nAfter debugging complete, no need to busy removing all debug() calls! Simply:\n```cpp\n#define NDEBUG\n```\nwould supress all debug() prints and assertion checks, completely no runtime overhead. For CMake or Visual Studio users, simply switch to `Release` build would supress debug() prints. Since they automatically define `NDEBUG` for you in `Release`, `RelWithDebInfo` and `MinSizeRel` build types.\n\n## 😏 Tested compilers\n\n- x86-64 gcc 4.8.1 (-std=c++11)\n- x86-64 gcc 13.2 (-std=c++20)\n- x86-64 gcc 9.1 (-std=c++11)\n- x86-64 gcc 13.2 (-std=c++14)\n- x86-64 gcc 9.1 (-std=c++17)\n- x86-64 clang 6.0.0 (-std=c++11 -stdlib=libc++)\n- armv7-a clang 9.0.0 (-std=c++11)\n- armv8-a clang 18.1.0 (-std=c++23)\n- x64 msvc v19.38 (/std:c++20)\n- arm64 msvc v19.38 (/std:c++14)\n- x64 msvc v19.31 (/std:c++17)\n- x86 msvc v19.14 (/std:c++11)\n- x64 msvc v19.latest (/std:c++latest)\n\nSee https://godbolt.org/z/jYdj4T44n\n\n## 🏅 To conclude\n\nTL;DR: This is a useful debugging utility the C++ programmers had all dreamed of:\n\n1. print using the neat comma syntax, easy-to-use\n2. supports printing STL objects including string, vector, tuple, optional, variant, unique_ptr, type_info, error_code, and so on.\n3. just add a member method named `repr`, e.g. `std::string repr() const { ... }` to support printing your custom class!\n4. classes that are not supported to print will be shown in something like `[TypeName@0xdeadbeaf]` where 0xdeadbeaf is it's address.\n5. highly configurable, customize the behaviour by defining the DEBUG_xxx macros (see below)\n6. when debug done, supress all debug messages by simply `#define NDEBUG`, the whole library is disabled at compile-time, no runtime overhead\n7. Thread safe, every line of message is always distinct, no annoying interleaving output rushing into console (typical experience when using cout)\n\n## 😜 Configurations\n\nHere is a list of configurable macros, define them **before** including this header file to take effect:\n\n* `#define DEBUG_LEVEL 0` (default when defined NDEBUG) - disable debug output, completely no runtime overhead\n* `#define DEBUG_LEVEL 1` (default when !defined NDEBUG) - enable debug output, prints everything you asked to print\n\n* `#define DEBUG_STEPPING 0` (default) - no step debugging\n* `#define DEBUG_STEPPING 1` - enable step debugging, stops whenever debug output generated, manually press ENTER to continue\n* `#define DEBUG_STEPPING 2` - enable step debugging, like 1, but trigger a 'trap' interrupt for debugger to catch instead\n\n* `#define DEBUG_SHOW_TIMESTAMP 0` - do not print timestamp\n* `#define DEBUG_SHOW_TIMESTAMP 1` - enable printing a timestamp for each line of debug output (e.g. \"09:57:32\")\n* `#define DEBUG_SHOW_TIMESTAMP 2` (default) - printing timestamp relative to program staring time rather than system real time\n\n* `#define DEBUG_SHOW_THREAD_ID 0` (default) - do not print the thread id\n* `#define DEBUG_SHOW_THREAD_ID 1` - print the current thread id\n\n* `#define DEBUG_SHOW_LOCATION 1` (default) - show source location mark before each line of the debug output (e.g. \"file.cpp:233\")\n* `#define DEBUG_SHOW_LOCATION 0` - do not show the location mark\n\n* `#define DEBUG_OUTPUT std::cerr \u003c\u003c` (default) - controls where to output the debug strings (must be callable as DEBUG_OUTPUT(str))\n\n* `#define DEBUG_PANIC_METHOD 0` - throws an runtime error with debug string as message when assertion failed\n* `#define DEBUG_PANIC_METHOD 1` (default) - print the error message when assertion failed, then triggers a 'trap' interrupt, useful for debuggers to catch, if no debuggers attached, the program would terminate\n* `#define DEBUG_PANIC_METHOD 2` - print the error message when assertion failed, and then call std::terminate\n* `#define DEBUG_PANIC_METHOD 3` - print the error message when assertion failed, do not terminate, do not throw any exception\n\n* `#define DEBUG_REPR_NAME repr` (default) - if an object x have a member function like `x.repr()` or a global function `repr` supporting `repr(x)`, then the value of `x.repr()` or `repr(x)` will be printed instead for this object\n\n* `#define DEBUG_RANGE_BRACE \"{}\"` (default) - controls format for range-like objects (supporting begin(x) and end(x)) in \"{1, 2, 3, ...}\"\n* `#define DEBUG_RANGE_COMMA \", \"` (default) - ditto\n\n* `#define DEBUG_TUPLE_BRACE \"{}\"` (default) - controls format for tuple-like objects (supporting std::tuple_size\u003cX\u003e) in \"{1, 2, 3}\"\n* `#define DEBUG_TUPLE_COMMA \", \"` (default) - ditto\n\n* `#define DEBUG_NAMED_MEMBER_MARK \": \"` (default) - used in debug::named_member and DEBUG_REPR, e.g. '{name: \"name\", age: 42}'\n\n* `#define DEBUG_MAGIC_ENUM magic_enum::enum_name` - enable printing enum in their name rather than value, if you have magic_enum.hpp\n\n* `#define DEBUG_UNSIGNED_AS_HEXADECIMAL 0` (default) - print unsigned integers as decimal\n* `#define DEBUG_UNSIGNED_AS_HEXADECIMAL 1` - print unsigned integers as hexadecimal\n* `#define DEBUG_UNSIGNED_AS_HEXADECIMAL 2` - print unsigned integers as full-width hexadecimal\n\n* `#define DEBUG_HEXADECIMAL_UPPERCASE 0` (default) - print hexadecimal values in lowercase (a-f)\n* `#define DEBUG_HEXADECIMAL_UPPERCASE 1` - print hexadecimal values in uppercase (A-F)\n\n* `#define DEBUG_SUPRESS_NON_ASCII 0` (default) - consider non-ascii characters in std::string as printable (e.g. UTF-8 encoded Chinese characters)\n* `#define DEBUG_SUPRESS_NON_ASCII 1` - consider non-ascii characters in std::string as not printable (print them in e.g. '\\xfe' instead)\n\n* `#define DEBUG_SHOW_SOURCE_CODE_LINE 1` - enable debug output with detailed source code level information (requires readable source file path)\n\n* `#define DEBUG_NULLOPT_STRING \"nullopt\"` (default) - controls how to print optional-like objects (supporting *x and (bool)x) when it is nullopt\n\n* `#define DEBUG_NULLPTR_STRING \"nullptr\"` (default) - controls how to print pointer-like objects (supporting static_cast\u003cvoid const volatile *\u003e(x.get())) when it is nullptr\n\n* `#define DEBUG_SMART_POINTER_MODE 1` (default) - print smart pointer as raw pointer address (e.g. 0xdeadbeaf)\n* `#define DEBUG_SMART_POINTER_MODE 2` - print smart pointer as content value unless nullptr (e.g. 42)\n* `#define DEBUG_SMART_POINTER_MODE 3` - print smart pointer as both content value and raw pointer address (e.g. 42@0xdeadbeaf)\n\n* `#define DEBUG_NAMESPACE_BEGIN` (default) - expose debug in the global namespace\n* `#define DEBUG_NAMESPACE_END` (default) - ditto\n\n* `#define DEBUG_NAMESPACE_BEGIN namespace mydebugger {` - expose debug in the the namespace `mydebugger`, and use it like `mydebugger::debug()`\n* `#define DEBUG_NAMESPACE_END }` - ditto\n\n* `#define DEBUG_CLASS_NAME debug` (default) - the default name for the debug class is `debug()`, you may define your custom name here\n\n## 💝 Questions?\n\nWhat's your opinion for this handy printing utility? Any suggestions or feature request would be welcome in the [GitHub issues](https://github.com/archibate/debug-hpp/issues)!\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farchibate%2Fdebug-hpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farchibate%2Fdebug-hpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farchibate%2Fdebug-hpp/lists"}