Drako0812
Drako0812

Reputation: 103

Why is fmt::format not accepting a string as an argument?

I've successfully used the fmt library before, so I'm not exactly sure why I'm having this problem. First I'll show you the code that is producing an error:

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.
        );
    }
}

And here is the build log (NOTE: I'm using VSCode as my editor and CMake to build the project using Visual Studio 2019's compiler):

[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

The errors make it sound like fmt doesn't have a fmt::formatter<std::string> specialization which doesn't sound right to me, so I've either misconfigured something, or not included a header or something. Frankly, I'm quite baffled. Once I have an answer, it'll probably be something silly knowing my luck. Anyway, thanks in advance for any help provided.

Upvotes: 3

Views: 4479

Answers (1)

Drako0812
Drako0812

Reputation: 103

Okay, so apparently the error was not being caused by what I thought it was being caused by (Thanks, Visual C++ compiler error messages, super helpful! /s ). So to explain what was actually going on:

  • Logger::Info calls a more generic function called Logger::Log(LoggingLevel level, const std::string & message).
  • Logger::Log also calls fmt::format inside of it to format up some additional information to save to the log.
  • One of the arguments of that fmt::format call is the level which then needs to be converted to a string (and I chose to make a ToString function instead of making a fmt::formatter for it).
  • The problem was the ToString function returns an std::optional<std::string> to "cleanly" handle invalid values. Well, apparently I forgot to call .value_or on the return value, and THAT was what was causing the error.

Unfortunately none of the error messages even mentioned anything to do with that line, so that was quite a few minutes/hours wasted.

Upvotes: 4

Related Questions