C++:如何使用 spdlog 打印自定义 class 指针?

C++ : how to use spdlog to print custom class pointer?

我遇到了一个小问题。 我需要使用 spdlog 来登录并且我有自定义的 classes。 因为 spdlog 能够处理 user defined classes,我可以用它来记录我的 classes.

但是,我是我的真实应用程序,我想用我的 class 的指针提供给 spdlog(因为存在多态性,但这不是重点)。 我的麻烦就在这里。 当我尝试用 class 的 unique_ptr 喂养 spdlog 时,它无法编译。

所以这里是一个 MWE:

#include <stdio.h>
#include <iostream>  
#include <fstream>
#include <string.h>  

#include <spdlog/spdlog.h>    //
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/fmt/ostr.h" // must be included to log object 

using namespace std;

struct my_type
{
    int i;
    template<typename OStream>
    friend OStream &operator<<(OStream &os, const my_type &c)
    {
        return os << "[my_type i=" << c.i << "]";
    }
};

template<typename OStream>
OStream &operator<<(OStream &os,const my_type* c)
{
    return os << "[my_type i=" << "pointer" << "]";
}

int main()  { 
    
    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
    spdlog::logger logger("log_test", console_sink);
    logger.set_level(spdlog::level::trace);
    auto pLog =std::make_shared<spdlog::logger>(logger); //register it if you need to access it globally
        
    std::unique_ptr<my_type> ptrA(new my_type{12});
    pLog->info("user defined type: {}", ptrA);  // of course *ptrA simply works, but in my application I have to give ptrA ...

    return 0;
}

我从编译器那里得到错误 gcc:

spdlog/fmt/bundled/core.h:1566:15: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = my_type; _Dp = std::default_delete<my_type>]’
const auto& arg = arg_mapper<Context>().map(val);

spdlog/fmt/bundled/core.h:1567:3: error: static assertion failed: Cannot format an argument. To make type T formattable provide a formatter<T> specialization: https://fmt.dev/latest/api.html#udt
static_assert(

spdlog/fmt/bundled/core.h:1184:15: error: use of deleted function ‘fmt::v8::detail::fallback_formatter<T, Char, Enable>::fallback_formatter() [with T = fmt::v8::detail::unformattable; Char = char; Enable = void]’
 Formatter f;
           ^
/spdlog/fmt/bundled/core.h:963:3: note: declared here
fallback_formatter() = delete;
^~~~~~~~~~~~~~~~~~
 spdlog/fmt/bundled/core.h:1185:28: error: ‘struct fmt::v8::detail::fallback_formatter<fmt::v8::detail::unformattable, char, void>’ has no member named ‘parse’
 parse_ctx.advance_to(f.parse(parse_ctx));
                      ~~^~~~~
 spdlog/fmt/bundled/core.h:1186:22: error: ‘struct fmt::v8::detail::fallback_formatter<fmt::v8::detail::unformattable, char, void>’ has no member named ‘format’
 ctx.advance_to(f.format(*static_cast<const T*>(arg), ctx));
                ~~^~~~~~

我猜问题出在 template<typename OStream> OStream &operator<<(OStream &os,const my_type* c)spdlogfmt 之间的交互。所以我试着玩了一下,但我被卡住了。

你有解决这个问题的想法,保持 pLog->info("user defined type: {}", ptrA); 吗?

问题来自库 fmt 自版本 8(由 spdlog 自版本 1.9.0 起使用),不再支持指针。 一个解决方案是使用包装器 class 来存储指针并精确 fmt 应该如何处理它。