简体   繁体   English

如何在 cpp 中定义一个宏来打印文件 function 行?

[英]How do I define a macro to print file, function, line in cpp?

I am trying to make a print function which prepends the print statement with file, function, and line number.我正在尝试打印 function,它在打印语句前面加上文件、function 和行号。

The function debug("test %d", 1) should print: function debug("test %d", 1)应该打印:

[src/main.cpp:main():8] test 1

This answer claims to do what I want, and almost does it, but doesn't work as-is.这个答案声称可以做我想做的事,并且几乎可以做到,但不能按原样工作。 (And the question is not the same as this one) Using that answer, I was able to come up with this macro: (而且这个问题与这个问题不一样)使用那个答案,我能够想出这个宏:

#include <cstdio>  //needed for printf
#define debug(a, args...) printf("[%s:%s():%d] " #a "\n", __FILE__, __func__ , __LINE__, ##args)

This is extremely close to what I want, but adds quotes around the string, like below.这与我想要的非常接近,但在字符串周围添加了引号,如下所示。 How can I print without the quotes?没有引号如何打印?

[src/main.cpp:main():8] "test 1"

There are 2 problems with your macro definition:您的宏定义有两个问题:

  1. It uses incorrect syntax它使用了不正确的语法
  2. The name of a variable may be passed as a ;变量的名称可以a ; in this case you cannot simply put the variable next to 2 string literals to do a concatenation.在这种情况下,您不能简单地将变量放在 2 个字符串文字旁边进行连接。

The latter problem can be solved by using a string and the + operator or simply using multiple printf s.后一个问题可以通过使用字符串和+运算符或简单地使用多个printf来解决。

If C++20 __VA_OPT__ is available, the following solution could be used.如果 C++20 __VA_OPT__可用,则可以使用以下解决方案。

#include <cstdio>
#include <utility>

namespace Logging
{
    template<typename ...Args>
    inline void Debug(size_t lineNumber, char const* filename, char const* functionName, char const* format, Args&&... args)
    {
        std::printf("[%s:%s():%zu] ", filename, functionName, lineNumber);
        std::printf(format, std::forward<Args>(args)...);
        std::printf("\n");
    }
}

#define debug(format, ...) ::Logging::Debug(__LINE__, __FILE__, __func__, format __VA_OPT__(,) __VA_ARGS__)

Pre C++ 20 you could create a helper object to deal with the case of a sue of the macro with just a single parameter Pre C++ 20 你可以创建一个帮助程序 object 来处理仅使用单个参数的宏的情况

#include <cstdio>
#include <utility>

namespace Logging
{
    class Logger
    {
    public:
        Logger(size_t lineNumber, char const* filename, char const* functionName, char const* format)
            : m_lineNumber(lineNumber), m_filename(filename), m_functionName(functionName), m_format(format)
        {}

        template<class ...Args>
        inline void Debug(Args&&... args)
        {
            std::printf("[%s:%s():%zu] ", m_filename, m_functionName, m_lineNumber);
            std::printf(m_format, std::forward<Args>(args)...);
            std::printf("\n");
        }
    private:
        size_t m_lineNumber;
        char const* m_filename;
        char const* m_functionName;
        char const* m_format;
    };
}

#define debug(format, ...) ::Logging::Logger(__LINE__, __FILE__, __func__, format).Debug(__VA_ARGS__)

Replace #a with just a :仅将#a替换为a

#define debug(a, args...) printf("[%s:%s():%d] " a "\n", __FILE__, __func__, __LINE__, ##args)

A single # followed by a macro parameter stringifies the parameter.单个#后跟宏参数将参数字符串化 IOW, it takes whatever the caller passes into the parameter and makes a string literal out of it. IOW,它接受调用者传递给参数的任何内容,并从中生成字符串文字。 For example:例如:

#define macro(a) #a

macro(1) would be "1" , macro(x+y) would be "x+y" , etc. macro(1)将是"1"macro(x+y)将是"x+y" ,等等。

If the parameter contains quote characters, they will be stored as actual characters in the string literal, which is not what you want in this situation.如果参数包含引号字符,它们将作为实际字符存储在字符串文字中,这不是您在这种情况下想要的。 Your parameter is being passed a string literal that you want to use as-is, so simple macro replacement will suffice, so you need to drop the # .您的参数正在传递一个您想按原样使用的字符串文字,因此简单的宏替换就足够了,因此您需要删除# You want the compiler to see "[%s:%s():%d] " "test %d" "\n" and thus merge them together into "[%s:%s():%d] test %d\n" , not to see "[%s:%s():%d] " "\"test %d\"" "\n" and merge them into "[%s:%s():%d] \"test %d\"\n" , which is what you are seeing happen in your original code.您希望编译器看到"[%s:%s():%d] " "test %d" "\n"并因此将它们合并到"[%s:%s():%d] test %d\n" ,看不到"[%s:%s():%d] " "\"test %d\"" "\n"并将它们合并到"[%s:%s():%d] \"test %d\"\n" ,这是您在原始代码中看到的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM