【发布时间】:2021-10-25 02:19:08
【问题描述】:
我遇到了一个小问题。
我需要使用spdlog 进行登录,并且我有自定义类。
既然spdlog 能够处理user defined classes,我可以用它来记录我的课程。
但是,我是我真正的应用程序,我想用我的类的指针来提供spdlog(因为存在多态性,但这不是重点)。
我的麻烦就来了。
当我尝试用我班级的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) 和spdlog 或fmt 之间的交互。所以我试着玩了一下,但我卡住了。
你有解决这个问题的想法吗,保持pLog->info("user defined type: {}", ptrA);?
【问题讨论】:
-
你总是可以从
std::unique_ptr和ptrA.get()得到一个原始指针。 -
或者由于涉及到用户定义的类型,所以为
OStream &operator<<(OStream &os, const std::unique_ptr<my_type>& c)添加一个重载 -
@IlCapitano 你是对的,但尝试一下我得到了
fmt/bundled/core.h:1347:47: error: call of overloaded ‘map(my_type* const&)’ is ambiguous typename Context::char_type>;fmt/bundled/core.h:1694:73: error: no matching function for call to 'fmt::v8:detail:arg_data<fmt::v8::detail::value<fmt::v8::basic_format_context<fmt::v8::appender, char> >::arg_data(<brace-enclosed initializer list>)’ detail::mapped_type_constant<Args, Context>::value>(args)...} {和fmt/bundled/core.h:1679:39: error: constexpr call flows off the end of the function static constexpr unsigned long long desc = -
@TedLyngmo 好像是个好主意,但是我一试,也出现编译错误:
spdlog/fmt/bundled/core.h:1308:5: error: static assertion failed: formatting of non-void pointers is disallowed static_assert(!sizeof(T), "formatting of non-void pointers is disallowed"); ^~~~~~~~~~~~~ -
@R.N Both suggestions seem to work with your example on godbolt。你能用一个可重现的例子来更新这个问题吗?
标签: c++ unique-ptr fmt spdlog