Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to print many variables with there name and their corresponding value in c++?

#include <bits/stdc++.h>
using namespace std;

#define __deb(X...) (cout << "[" << #X << "]:" << X)
template <typename... type>
void debug(type &&... args)
{
    ((__deb(args)), ...);
}

int main()
{
    int a = 1, b = 3;
    debug(a,b);
    return 0;
}

I got output like [args]:1[args]:3 but I wanted output like [a]:1[b]:3

like image 778
Ayushman Sharma Avatar asked Dec 11 '22 00:12

Ayushman Sharma


2 Answers

One way could be to quote all the macro arguments using #__VA_ARGS__ and parse that string in the C++ function.

Example:

#include <iostream>
#include <sstream>
#include <string>
#include <utility>

template<typename T, typename... Args>
std::string debug_detail(const char* names, T&& var, Args&&... args) {
    std::ostringstream builder;

    // find variable end
    const char* end = names;
    while(*end != ',' && *end != '\0') ++end;

    // display one variable
    (builder << ' ').write(names, end - names) << '=' << var;

    // continue parsing?
    if constexpr(sizeof...(Args) > 0) {
        // recursively call debug_detail() with the new beginning for names
        builder << debug_detail(end + 1, std::forward<Args>(args)...);
    }

    return builder.str();
}

template<typename... Args>
void debug_entry(const char* file, int line, const char* func,
                 const char* names, Args&&... args) {
    std::ostringstream retval;

    // common debug info
    retval << file << '(' << line << ") " << func << ':';

    // add variable info
    retval << debug_detail(names, std::forward<Args>(args)...) << '\n';

    std::cout << retval.str();
}

// the actual debug macro
#define debug(...) \
    debug_entry(__FILE__,__LINE__,__func__,#__VA_ARGS__,__VA_ARGS__)

int main() {
    int foo = 1;
    const double bar = 2;
    const std::string Hello = "world";

    debug(foo,bar,Hello);
}

Possible output:

example.cpp(49) main: foo=1 bar=2 Hello=world

Demo


A C++20 version using std::source_location:

#include <source_location>

template<typename... Args>
void debug_entry(const std::source_location location,
                 const char* names, Args&&... args) {
    std::ostringstream retval;

    // common debug info
    retval << location.file_name() << '(' << location.line() << ','
           << location.column() << ") " << location.function_name() << ':';

    // add variable info
    retval << debug_detail(names, std::forward<Args>(args)...) << '\n';

    std::cout << retval.str();
}

// the actual debug macro
#define debug(...) \
    debug_entry(std::source_location::current(), #__VA_ARGS__,__VA_ARGS__)

Demo

like image 113
Ted Lyngmo Avatar answered May 10 '23 23:05

Ted Lyngmo


Here's my humble attempt, which uses a macro FOO to create a pair of the variable name and its value, and passes the arguments to a variadic function:

#include <utility>
#include <iostream>

#define FOO(var) std::make_pair(std::string(#var), var)

template <typename T>
void __deb(std::pair<std::string, T> arg) { std::cout << "[" << arg.first << "]:" << arg.second; }

template <typename... type>
void debug(std::pair<std::string, type> &&... args)
{
    (__deb(args), ...);
}

int main()
{
    int a = 1, b = 3;
    debug(FOO(a), FOO(b));
}

Demo


Alternatively, to avoid having a macro call FOO for each variable in debug, you could define debug as a macro that accepts #__VA_ARGS__ (string of arguments) and __VA_ARGS__ (argument values). Then parse each variable name and value:

#include <iostream>
#include <sstream>
#include <stdio.h>

#define debug(...) debug_print(#__VA_ARGS__,__VA_ARGS__)

template <typename T>
void __deb(std::istringstream &ss, T arg)
{
    //Extract name from stream
    std::string name;
    std::getline(ss, name, ',');
    //trim leading space
    const auto pos(name.find_first_not_of(" "));
    name.erase(0, pos);
    std::cout << "[" << name << "]:" << arg;
}

template <typename... type>
void debug_print(const char* names, type&&...args)
{
    std::istringstream ss(names);
    (__deb(ss, args), ...);
}


int main()
{
    int a = 1, b = 3, c = 4;
    debug(a, b, c);
}

Demo

like image 22
jignatius Avatar answered May 11 '23 00:05

jignatius