为什么fmt :: format不接受字符串作为参数?

3

我之前成功地使用过fmt库,所以我不确定为什么会出现这个问题。首先,我将展示产生错误的代码:

void Logger::AttachSink(const std::string & id, LogSink sink) {
    using namespace std::literals;
    auto id_found = sinks.find(id) != std::endl(sinks);
    if(!id_found) {
        sinks.insert(std::make_pair(id, sink));
        Info(
            fmt::format(
                "Sink \"{}\" Attached"s,
                id
            ) // This is the line where the error is apparently happening, and I'm assuming the `id` is the culprit for some reason.
        );
    }
}

以下是构建日志(注意:我使用VSCode作为编辑器,并使用CMake使用Visual Studio 2019编译器构建项目):

[main] Building folder: [WORKSPACE]
[build] Starting build
[proc] Executing command: "C:\Program Files\CMake\bin\cmake.exe" --build [WORKSPACE]/build --config Debug --target ALL_BUILD -- /maxcpucount:6
[build] Microsoft (R) Build Engine version 16.7.0+b89cb5fde for .NET Framework
[build] Copyright (C) Microsoft Corporation. All rights reserved.
[build] 
[build]   logging.cpp
[build] [WORKSPACE]\build\vcpkg_installed\x64-windows\include\fmt\core.h(1073,9): error C2338: Cannot format argument. To make type T formattable provide a formatter<T> specialization: https://fmt.dev/latest/api.html#formatting-user-defined-types [[WORKSPACE]\build\drakeng\drakeng.vcxproj]
[build] [WORKSPACE]\build\vcpkg_installed\x64-windows\include\fmt\core.h(1070): message : while compiling class template member function 'int fmt::v7::detail::arg_mapper<Context>::map(...)' [[WORKSPACE]\build\drakeng\drakeng.vcxproj]
[build]           with
[build]           [
[build]               Context=fmt::v7::basic_format_context<std::back_insert_iterator<fmt::v7::detail::buffer<char>>,char>
[build]           ]
[build] [WORKSPACE]\build\vcpkg_installed\x64-windows\include\fmt\core.h(1259): message : see reference to function template instantiation 'int fmt::v7::detail::arg_mapper<Context>::map(...)' being compiled [[WORKSPACE]\build\drakeng\drakeng.vcxproj]
[build]           with
[build]           [
[build]               Context=fmt::v7::basic_format_context<std::back_insert_iterator<fmt::v7::detail::buffer<char>>,char>
[build]           ]
[build] [WORKSPACE]\build\vcpkg_installed\x64-windows\include\fmt\core.h(1084): message : see reference to class template instantiation 'fmt::v7::detail::arg_mapper<Context>' being compiled [[WORKSPACE]\build\drakeng\drakeng.vcxproj]
[build]           with
[build]           [
[build]               Context=fmt::v7::basic_format_context<std::back_insert_iterator<fmt::v7::detail::buffer<char>>,char>
[build]           ]
[build] [WORKSPACE]\build\vcpkg_installed\x64-windows\include\fmt\core.h(1241): message : see reference to alias template instantiation 'fmt::v7::detail::mapped_type_constant<const std::basic_string<char,std::char_traits<char>,std::allocator<char>>,Context>' being compiled [[WORKSPACE]\build\drakeng\drakeng.vcxproj]
[build]           with
[build]           [
[build]               Context=fmt::v7::basic_format_context<std::back_insert_iterator<fmt::v7::detail::buffer<char>>,char>
[build]           ]
[build] [WORKSPACE]\build\vcpkg_installed\x64-windows\include\fmt\core.h(1400): message : see reference to function template instantiation 'unsigned __int64 fmt::v7::detail::encode_types<Context,const std::basic_string<char,std::char_traits<char>,std::allocator<char>>,>(void)' being compiled [[WORKSPACE]\build\drakeng\drakeng.vcxproj]
[build]           with
[build]           [
[build]               Context=fmt::v7::basic_format_context<std::back_insert_iterator<fmt::v7::detail::buffer<char>>,char>
[build]           ]
[build] [WORKSPACE]\build\vcpkg_installed\x64-windows\include\fmt\core.h(1834): message : see reference to class template instantiation 'fmt::v7::format_arg_store<fmt::v7::basic_format_context<std::back_insert_iterator<fmt::v7::detail::buffer<char>>,char>,const std::basic_string<char,std::char_traits<char>,std::allocator<char>>>' being compiled [[WORKSPACE]\build\drakeng\drakeng.vcxproj]
[build] [WORKSPACE]\drakeng\logging.cpp(24): message : see reference to function template instantiation 'std::basic_string<char,std::char_traits<char>,std::allocator<char>> fmt::v7::format<std::string,const std::string&,char>(const S &,const std::string &)' being compiled [[WORKSPACE]\build\drakeng\drakeng.vcxproj]
[build]           with
[build]           [
[build]               S=std::string
[build]           ]
[build] Build finished with exit code 1

错误信息让人觉得fmt没有fmt::formatter<std::string>的专门化(specialization),这听起来不太对,所以我可能配置错误,或者没有包含头文件等等。老实说,我很困惑。一旦有了答案,可能只是我的运气问题导致了一些愚蠢的错误。无论如何,提供的任何帮助,先行致谢。

是的,我意识到我可以使用连接来组合字符串,但如果我想使格式化字符串更复杂,这肯定是可能的。而且,我很确定我以前用过 fmt 库做过这件事,这就是为什么我感到困惑的原因。 - Drako0812
1个回答

3

好的,显然错误并不是我原以为的那个导致的(谢谢Visual C++编译器错误信息,真是太有帮助了!/s)。所以现在来解释一下实际发生了什么:

  • Logger::Info 调用一个更通用的函数 Logger::Log(LoggingLevel level, const std::string & message)
  • Logger::Log 在其中也调用了 fmt::format 来格式化一些额外的信息以保存到日志中。
  • 其中一个参数是该 fmt::format 调用的 level,需要将其转换为字符串(我选择创建一个 ToString 函数而不是创建一个 fmt::formatter)。
  • 问题出在 ToString 函数返回一个 std::optional<std::string> 来“干净地”处理无效值。很明显,我忘记在返回值上调用 .value_or,这正是导致错误的原因。

不幸的是,所有的错误信息都没有提到与那行代码有关的任何内容,所以浪费了相当多的时间/小时。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接