A dbg(…) macro for C++

Overview

dbg(…)

Build status Try it online License: MIT

A macro for printf-style debugging fans.

Debuggers are great. But sometimes you just don't have the time or patience to set up everything correctly and just want a quick way to inspect some values at runtime.

This projects provides a single header file with a dbg(…) macro that can be used in all circumstances where you would typically write printf("…", …) or std::cout << …. But it comes with a few extras.

Examples

#include <vector>
#include <dbg.h>

// You can use "dbg(..)" in expressions:
int factorial(int n) {
  if (dbg(n <= 1)) {
    return dbg(1);
  } else {
    return dbg(n * factorial(n - 1));
  }
}

int main() {
  std::string message = "hello";
  dbg(message);  // [example.cpp:15 (main)] message = "hello" (std::string)

  const int a = 2;
  const int b = dbg(3 * a) + 1;  // [example.cpp:18 (main)] 3 * a = 6 (int)

  std::vector<int> numbers{b, 13, 42};
  dbg(numbers);  // [example.cpp:21 (main)] numbers = {7, 13, 42} (std::vector<int>)

  dbg("this line is executed");  // [example.cpp:23 (main)] this line is executed

  factorial(4);

  return 0;
}

The code above produces this output (try it yourself):

dbg(…) macro output

Features

  • Easy to read, colorized output (colors auto-disable when the output is not an interactive terminal)
  • Prints file name, line number, function name and the original expression
  • Adds type information for the printed-out value
  • Specialized pretty-printers for containers, pointers, string literals, enums, std::optional, etc.
  • Can be used inside expressions (passing through the original value)
  • The dbg.h header issues a compiler warning when included (so you don't forget to remove it).
  • Compatible and tested with C++11, C++14 and C++17.

Installation

To make this practical, the dbg.h header should be readily available from all kinds of different places and in all kinds of environments. The quick & dirty way is to actually copy the header file to /usr/include or to clone the repository and symlink dbg.h to /usr/include/dbg.h.

git clone https://github.com/sharkdp/dbg-macro
sudo ln -s $(readlink -f dbg-macro/dbg.h) /usr/include/dbg.h

If you don't want to make untracked changes to your filesystem, check below if there is a package for your operating system or package manager.

On Arch Linux

You can install dbg-macro from the AUR:

yay -S dbg-macro

With vcpkg

You can install the dbg-macro port via:

vcpkg install dbg-macro

Configuration

  • Set the DBG_MACRO_DISABLE flag to disable the dbg(…) macro (i.e. to make it a no-op).
  • Set the DBG_MACRO_NO_WARNING flag to disable the "'dbg.h' header is included in your code base" warnings.

Advanced features

Multiple arguments

You can pass multiple arguments to the dbg(…) macro. The output of dbg(x, y, z) is same as dbg(x); dbg(y); dbg(z);:

dbg(42, "hello world", false);

Note that you have to wrap "unprotected commas" in parentheses:

dbg("a vector:", (std::vector<int>{2, 3, 4}));

Hexadecimal, octal and binary format

If you want to format integers in hexadecimal, octal or binary representation, you can simply wrap them in dbg::hex(…), dbg::oct(…) or dbg::bin(…):

const uint32_t secret = 12648430;
dbg(dbg::hex(secret));

Printing type names

dbg(…) already prints the type for each value in parenthesis (see screenshot above). But sometimes you just want to print a type (maybe because you don't have a value for that type). In this case, you can use the dbg::type<T>() helper to pretty-print a given type T. For example:

template <typename T>
void my_function_template() {
  using MyDependentType = typename std::remove_reference<T>::type&&;
  dbg(dbg::type<MyDependentType>());
}

Print the current time

To print a timestamp, you can use the dbg::time() helper:

dbg(dbg::time());

Customization

If you want dbg(…) to work for your custom datatype, you can simply overload operator<< for std::ostream&:

std::ostream& operator<<(std::ostream& out, const user_defined_type& v) {
  out << "";
  return out;
}

If you want to modify the type name that is printed by dbg(…), you can add a custom get_type_name overload:

// Customization point for type information
namespace dbg {
    std::string get_type_name(type_tag<bool>) {
        return "truth value";
    }
}

Development

If you want to contribute to dbg-macro, here is how you can build the tests and demos:

Make sure that the submodule(s) are up to date:

git submodule update --init

Then, use the typical cmake workflow. Usage of -DCMAKE_CXX_STANDARD=17 is optional, but recommended in order to have the largest set of features enabled:

mkdir build
cd build
cmake .. -DCMAKE_CXX_STANDARD=17
make

To run the tests, simply call:

make test

You can find the unit tests in tests/basic.cpp.

Acknowledgement

This project is inspired by Rusts dbg!(…) macro.

Comments
  • Windows Support

    Windows Support

    Pull Request Status: Ready

    Previous Pull Request: #31

    Important Changes

    • Improved CMakeLists.txt.
    • Improved .travis.yml.
    • Added appveyor.yml.
    • Separated the tests.
    • Separated the examples.
    • Colored Ouput works on Windows.
    • Added support for std::array
    • Added support for std::list

    Windows Build

    • MSVC 19.16.27030.1 (Visual Studio 15 2017)
    • MSVC 19.21.27702.2 (Visual Studio 16 2019)

    Linux Build

    • GCC 7.0
    • GCC 8.0
    • Clang 8.0.1
    • Clang 7.1.0

    macOS Build

    • AppleClang 10.0.0.10001145
    • AppleClang 10.0.1.10010046
    opened by ghost 15
  • Adds empty dbg calls

    Adds empty dbg calls

    This allows users to call dbg() with no arguments to print out dummy text "dbg call reached".
    Works with or without DBG_MACRO_DISABLE being defined.
    Closes #64

    opened by DerekCresswell 13
  • `Type does not support the << ostream operator` on custom type

    `Type does not support the << ostream operator` on custom type

    Here is the code.

    // a.h
    #include "imgui.h"
    
    std::ostream& operator<<(std::ostream& out, const ImVec2& v);
    
    // a.cpp
    std::ostream& operator<<(std::ostream& out, const ImVec2& v) {
          out << v.x << ", " << v.y;
          return out;
    }
    
    // main.cpp
    #include <iostream>
    #include "imgui.h"
    #include "a.h"
    #include "dbg.h"
    
    void test (){
        auto pos = ImVec2(1,2);
        std::cout << pos;   // it's ok
        dbg(pos);    //  Type does not support the << ostream operator
    }
    
    opened by Aincvy 10
  • Add a flag to enable or disable dbg for release builds.

    Add a flag to enable or disable dbg for release builds.

    Not sure if there's currently a way to set a flag to enable or disable dbg depending on whether or not it's a debug build. If there is a flag, it should probably be documented, if not, maybe some kind of #define to effectively make the dbg macro do nothing.

    opened by Jackojc 9
  • Idea: add type information?

    Idea: add type information?

    We could potentially use typeid(…).name() to add type information about the debugged value. This could be really helpful if used somewhere inside expressions where the type is not completely obvious.

    We would have to find a cross-compiler way to demangle the typeid(…).name() string...

    opened by sharkdp 9
  • Add some control of floating point formatting

    Add some control of floating point formatting

    This allows users to customize the output of floating point types by adjusting the flags of a stream in the same way as one normally would.

    I also added the equivalent support for std::complex of floating point types in a C++11-compatible way (this would not require copying the code in C++17).

    opened by VasilySotnikov 8
  • Setting CMAKE_CXX_STANDARD to 11

    Setting CMAKE_CXX_STANDARD to 11

    I had some difficulties compiling on macOS with AppleClang and realized that CMAKE_CXX_STANDARD is not set for the project. I think this should be set, and I believe if the project is embedded as a submodule, the standard will propagate to submodules from the root project, right? So, this should not cause any problem.

    opened by amirmasoudabdol 8
  • <ios> and <iomanip> flags

    and flags

    Hello!

    This project is very great, thank you!

    I often need to print values as hexadecimal, and bonus point as binary. It would be nice if this library support it.

    Maybe dbg(std::hex, number)? This does break the implicit rull that arguments are all "dbged" but it could work. Maybe dbg::dbg(dbg::hex(number))?

    If you do not have time, I can PR this feature if you are ok on the concept and the way of doing it!

    EDIT: maybe I missed the already-existing feature to print as hexadecimal!

    opened by mhammerc 8
  • Broken output of containers

    Broken output of containers

    See example below. https://godbolt.org/z/vnxaqq

    #include <dbg.h>
    
    int main()
    {
        std::vector<std::pair<std::string, int>> container = {
            {"30+2", 32}, {"30-2", 28}, {"30*2", 60}
        };
        dbg(container);
    }
    

    Here we have a vector of pairs of strings. Despite the library has pretty_print overloads for std::pair, std::string, and container they don't fully work with each other. It seems that the reason is the fact, that pretty_print overloads for std::pair and std::string are defined just after container overload and thus they aren't visible from pretty_print overload for containers.

    A possible solution is adding declarations for all the pretty_print overloads before their definitions. For e.g. in my example, adding declarations for pair and string overloads before container overload fixes the problem.

    inline bool pretty_print(std::ostream& stream, const std::string& value);
    
    template <typename T1, typename T2>
    inline bool pretty_print(std::ostream& stream, const std::pair<T1, T2>& value);
    
    
    
    template <typename Container>
    inline typename std::enable_if<detail::is_container<const Container&>::value,
                                   bool>::type
    pretty_print(std::ostream& stream, const Container& value) {
    
    bug help wanted 
    opened by YarikTH 6
  • Made colorized output disabled by default on windows. Colorized output can be enabled with DBG_MACRO_COLORIZED_OUTPUT_WINDOWS.

    Made colorized output disabled by default on windows. Colorized output can be enabled with DBG_MACRO_COLORIZED_OUTPUT_WINDOWS.

    ANSI colors on windows are disabled by default.

    Colorized output should also be disabled on windows by default to avoid the printing of unwanted control characters.

    I've added the define "DBG_MACRO_COLORIZED_OUTPUT_WINDOWS" for this purpose.

    opened by lringham 6
  • Add support for empty

    Add support for empty "dbg()" calls.

    The dbg-macro call includes file, line and function information anyway, so empty

    dbg();
    

    calls can be helpful as well (instead of a dummy dbg("this is executed") call).

    opened by sharkdp 6
  • Support for container adapters

    Support for container adapters

    It would be great if the macro had support for container adapters std::stack, std::queue and std::priority_queue assuming these weren't left out for some specific reasons

    opened by nocoinman 0
  • How to force print the full content, not the one with ellipsis

    How to force print the full content, not the one with ellipsis

    How can i print all the full content of a variable such as the follows:

    [.\xxx.cpp:19 (xxfunction)] tree = {1, 2, 4, 5, 3, 6, -1, -1, -1, -1, -1, -1, -1,size:13} (std::vector<int>)
    

    or not:

    [.\xxx.cpp:19 (xxfunction)] tree = {1, 2, 4, 5, 3, 6, -1, -1, -1, -1, ... size:13} (std::vector<int>)
    

    Is there a macro to set it up?

    opened by hhhxiao 2
  • Nested dbg(...) expansion as not expected

    Nested dbg(...) expansion as not expected

    #include <vector>
    #include "dbg.h"
    
    // You can use "dbg(..)" in expressions:
    int factorial(int n) {
      if (dbg(dbg(n) <= 1)) {
        return dbg(1);
      } else {
        return dbg(n * factorial(n - 1));
      }
    }
    
    int main() {
      std::string message = "hello";
      dbg(message);  // [example.cpp:15 (main)] message = "hello" (std::string)
    
      const int a = 2;
      const int b = dbg(3 * a) + 1;  // [example.cpp:18 (main)] 3 * a = 6 (int)
    
      std::vector<int> numbers{b, 13, 42};
      dbg(numbers);  // [example.cpp:21 (main)] numbers = {7, 13, 42} (std::vector<int>)
    
      dbg("this line is executed");  // [example.cpp:23 (main)] this line is executed
    
      factorial(4);
    
      return 0;
    }
    

    Screen Shot 2022-10-29 at 11 54 24

    enhancement 
    opened by zhouzq-thu 2
  • Support always on colors

    Support always on colors

    I'm using dbg() in a test that runs via ctest which prevents any colors from appearing - as ctest buffers stdout so it has the option of not showing any output if the tests passed.

    Running the test binary without ctest gives proper colors.

    Having a way to enable coloring regardless of isatty would be great. Something like #DBG_MACRO_COLOR_ALWAYS (akin to grep --color=always).

    good first issue 
    opened by dufferzafar 2
Releases(v0.4.0)
Owner
David Peter
David Peter
std::tuple like methods for user defined types without any macro or boilerplate code

Boost.PFR This is a C++14 library for very basic reflection that gives you access to structure elements by index and provides other std::tuple like me

Antony Polukhin 145 Dec 18, 2022
Header-only, non-intrusive and macro-free runtime reflection system in C++

Header-only runtime reflection system in C++ The reflection system was born within EnTT and is developed and enriched there. This project is designed

Michele Caini 452 Jan 4, 2023
Nameof operator for modern C++, simply obtain the name of a variable, type, function, macro, and enum

_ _ __ _____ | \ | | / _| / ____|_ _ | \| | __ _ _ __ ___ ___ ___ | |_ | | _| |

Daniil Goncharov 1.5k Jan 4, 2023
Easy to use, header only, macro generated, generic and type-safe Data Structures in C

C Macro Collections Easy to use, header only, macro generated, generic and type-safe Data Structures in C. Table of Contents Installation Contributing

Leonardo Vencovsky 347 Jan 8, 2023
Easy to use, header only, macro generated, generic and type-safe Data Structures in C

C Macro Collections Easy to use, header only, macro generated, generic and type-safe Data Structures in C. Table of Contents Installation Contributing

Leonardo Vencovsky 345 Jan 5, 2023
Nameof operator for modern C++, simply obtain the name of a variable, type, function, macro, and enum

_ _ __ _____ | \ | | / _| / ____|_ _ | \| | __ _ _ __ ___ ___ ___ | |_ | | _| |

Daniil Goncharov 1.5k Jan 8, 2023
The littlest Bluetooth macro pad

The littlest wireless macro pad! AWWWWW!!! (c) 2021 Zack Freedman and Voidstar Lab. Licensed CC-BY-NC (credit me and don't sell it) Built partially on

Zack Freedman 11 Dec 29, 2022
match(it): A lightweight header-only pattern-matching library for C++17 with macro-free APIs.

match(it): A lightweight header-only pattern-matching library for C++17 with macro-free APIs. Features Easy to get started. Single header library. Mac

Bowen Fu 434 Dec 27, 2022
Macro keypad and rotary input based on the ATmega32U4 Pro Micro board

JC-Pro-Macro Macro keypad and rotary input based on the ATmega32U4 Pro Micro Videos: Development: https://www.youtube.com/watch?v=g-XJLiv03rI Assembly

Jeremy S Cook 13 Oct 26, 2022
WTD is a python tool for replacing values with the C preprocessor macro which defined them.

Where's That Define WTD is a python tool for replacing values with the C preprocessor macro which defined them. An example of this is when trying to u

Caleb Connolly 5 Mar 28, 2022
🍋 Macro creation tool for MacOS

?? Lime Macro creation tool for MacOS Why Does lime require accessibility? Lime requires the Accessibility API to perform macro actions, such as press

AshPerson 1 Nov 27, 2021
Brainf.h - A C macro implementation of a brainf*ck interpreter

brainf.h - A C macro implementation of a brainf*ck interpreter #include <stdlib.h> #include <stdio.h> #define BRAINF(c){char*p,*b,*u,*i;p=b=calloc(300

null 4 Jan 1, 2022
Visual Studio and GCC precompiled header macro for CMake

cmake-precompiled-header Precompiled header setup for CMake. Supported CMake generators: Visual Studio NMake Makefiles Unix Makefiles (GCC) MinGW Make

Lars Christensen 157 Nov 6, 2022
CMake macro to determine the language of a header file

CMake Determine Header Language CMake macro to determine the language of a header file. Status Travis CI (Ubuntu) AppVeyor (Windows) Coverage Biicode

ポリ平方 POLYSQUARE 4 Dec 7, 2018
A C++14 macro to get the type of the current class without naming it

self_macro C++14 header only library that exposes a macro that creates a type alias for the current class without naming it. Also exposes macros that

Mital Ashok 10 Dec 12, 2022
Macro magic for declaring/calling Objective-C APIs from C11 or C++. Preloads selectors, chooses the correct objc_msgSend to call per method/platform.

OC - Easily Declare/Invoke Objective-C APIs from C11 or C++11 Usage // Call class and instance methods: NSWindow* const nswindow = oc_cls(NSWindow,new

Garett Bass 46 Dec 24, 2022
std::tuple like methods for user defined types without any macro or boilerplate code

Boost.PFR This is a C++14 library for very basic reflection that gives you access to structure elements by index and provides other std::tuple like me

Boost.org 1.1k Dec 23, 2022