【问题标题】:c++ print current function input argument type, name, and valuec++ 打印当前函数输入参数类型、名称和值
【发布时间】:2021-12-08 20:55:48
【问题描述】:

我正在寻找一种允许记录函数输入参数的功能。例如:

void func(std::string& input_name, const int n){

     // print current function's inputs' type, name, and value
}

函数调用后,会打印或读取字符串,

input1:
    type: std::string,
    name: input_name,
    value: "something",
input2:
    type: int,
    name: n,
    value: 12,

有人对这样的目标有建议吗

------------编辑

如果无法打印类型或名称,我也可以。 我对接近此的解决方案很灵活,例如我们是否可以获得输入参数列表等。

【问题讨论】:

  • 要进行字符串化,目前必须使用 MACRO。
  • C++ 没有 introspection 所以这不可能自动化。预期的输出只能通过打印实际类型和变量名来实现。
  • @Someprogrammerdude 是否意味着我们必须明确地写出打印的输入值的名称,或者有没有办法获取它们的列表
  • 你想在函数中获取类型名称,以便在函数中写cout << type_of_arg或类似的东西吗?或者您是否正在寻找某种自动化方式来打印所有功能的信息?我不完全清楚你在找什么。
  • 您可以使用普通输出流和<< 打印出的值。变量名称和类型需要硬编码。

标签: c++ debugging logging


【解决方案1】:

打印变量的类型和值相当简单。但是变量名在运行时不存在,因此在不对其进行硬编码的情况下,将变量名作为字符串获取的唯一方法是在编译时使用宏。宏具有字符串化标记的功能。

试试这样的(对不起,这是凭记忆,我目前无法使用编译器,我将在今天晚些时候更新):

#include <iomanip>
#include <typeinfo>
#include <type_traits>

template <typename T>
std::string getTypeName()
{
    // TODO: to get a more human-readable output, use
    // if-constexpr, or template specialization, or one
    // of the solutions from https://stackoverflow.com/q/281818/65863... 
    return typeid(T).name();
} 

template<typename T>
std::string stringify(const T& param)
{
    std::ostringstream oss;
    if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, char*> || std::is_same_v<T, const char*>)
        oss << std::quoted(param);
    else
        oss << param;
    return oss.str();
}

template <typename T>
void doLog(int num, std::string_view name, const T& value)
{
    std::cout << "input" << num << ":" << std::endl
        << "\ttype: " << getTypeName<T>() << "," << std::endl
        << "\tname: " << #param << "," << std::endl
        << "\tvalue: " << stringify(param) << "," << std::endl;
} 

#define LOG(num, param) doLog(num, #param, param)

void func(std::string& input_name, const int n){
    LOG(1, input_name)
    LOG(2, n)
}

【讨论】:

  • 再做一些工作,我们甚至可以通过iterating over variadic MACRO 获得LOG_PARAMS(input_name, n)(即使手动LOG_0LOG_1LOG_2、..、LOG_8 可能就足够了)。
  • @Jarod42 是的,虽然我的宏功夫不是很好,所以我没有提到它。
【解决方案2】:

这是一个使用模板而不是宏的开始: (确实添加了 typeid.name 可以输出错误名称的概念)

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

namespace details
{
    //-------------------------------------------------------------------------
    // formatters for parameters to functions
    //

    template<typename type_t>
    std::string format(const type_t& value)
    {
        std::ostringstream os;
        os << typeid(type_t).name() << ":";
        os << value;
        return os.str();
    }

    // output boolean as text
    std::string format(const bool& value)
    {
        return value ? std::string("bool:true") : std::string("bool:false");
    }

    // add quotes to string
    std::string format(const char* value)
    {
        std::ostringstream os;
        os << "const char*:\"";
        os << value;
        os << "\"";
        return os.str();
    }

    // recursively log all parameters
    template<typename arg_t, typename... args_t>
    inline void log_parameters(bool comma, const arg_t& arg, args_t... args)
    {
        if (comma) std::cout << ", ";
        std::cout << format(arg);

        if constexpr (sizeof...(args_t) > 0)
        {
            // true is print separating comma at next call
            log_parameters(true, std::forward<args_t>(args)...);
        }
    }

    //-------------------------------------------------------------------------

    template<typename... args_t>
    inline void log(const char* function, args_t... args)
    {
        std::cout << "function call to : " << function << "(";

        // if there are any arguments to log do so
        if constexpr (sizeof...(args_t) > 0)
        {
            // false == do not print a comma on first call
            log_parameters(false, std::forward<args_t>(args)...);
        }
        std::cout << ");\n";
    }
}

void my_function(const bool x, const int y, const char* str)
{
    details::log(__FUNCTION__, x, y, str);
}

int main()
{
    my_function(1, 42, "Hello world!");
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-08
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    相关资源
    最近更新 更多