如何在C++中打印具有名称和相应值的多个变量?

nhaq1z21  于 2023-05-08  发布在  其他
关注(0)|答案(3)|浏览(145)

考虑:

#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;
}

我得到了像[args]:1[args]:3这样的输出,但我想要像[a]:1[b]:3这样的输出。

j2cgzkjk

j2cgzkjk1#

一种方法是使用#__VA_ARGS__引用所有宏参数,并在C++函数中解析该字符串。
示例:

#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);
}

可能的输出:

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

Demo
使用std::source_location的C++20版本:

#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

g2ieeal7

g2ieeal72#

下面是我的一个简单尝试,它使用一个宏FOO来创建一对变量名和它的值,并将参数传递给一个可变参数函数:

#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
或者,为了避免对debug中的每个变量都使用宏调用FOO,可以将debug定义为接受#__VA_ARGS__(参数字符串)和__VA_ARGS__(参数值)的宏。然后解析每个变量名和值:

#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

yhqotfr8

yhqotfr83#

问题是MACRO是在void debug(type &&... args)的上下文中使用的,这对ab这两个名称并不熟悉。
一个可能的解决方案是实现一个更大的MACRO,它包含几个var,并调用一个处理单个var的子MACRO(您已经实现了)。
这样,初始的MACRO调用将发生在具有所需变量的调用函数的上下文中

相关问题