I am facing a little problem.
I need to use spdlog
to log and I have custom classes.
And since, spdlog
is able to deal with user defined classes, I could use it log my classes.
But, I my real application, I would like to feed spdlog
with a pointer of my class (because there is polymorphism but it's not the point here).
And here goes my troubles.
When I try to feed spdlog
with a unique_ptr
of my class, it does not compile.
So here a 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;
}
and I get errors from the compiler 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));
~~^~~~~~
I guess the problem is comming from the interaction between template<typename OStream> OStream &operator<<(OStream &os,const my_type* c)
and spdlog
or fmt
. So I tried to play a bit around but I am stuck.
Do you have ideas to solve this problem, keeping pLog->info("user defined type: {}", ptrA);
?
The problem comes from the library fmt
since version 8 (used by spdlog
since version 1.9.0), pointers are no longer supported.
A solution can be to use a wrapper class to store the pointer and precise how fmt
should deal with it.