Search code examples
c++homebrewfmt

Why does fmt::make_format_args work when using homebrew-installed libfmt, but doesn't work when I link with the version I built?


I am currently using libfmt for C++, and I am getting an error that I don't think I should be getting. The code works sometimes, but it doesn't at other times.

When I am linking libfmt from the homebrew installed location(I am on MacOS), it works completely. When I am linking statically from the one I build, using cd $(PATH_FMT) && mkdir -p build && cd build && cmake .. && make. I then link with LDFLAGS += $(PATH_FMT)/build/libfmt.a. The difference between the two is whether or not the following line is commented out in my makefile: CCFLAGS += -I/opt/homebrew/include. The code is as follows:

#define FMT_HEADER_ONLY
#include <fmt/core.h>
#include <fmt/format.h>

.
.
.

template<typename... Ts> static inline std::string format(const std::string &s, Ts &&...ts) {
    return fmt::vformat(std::string_view(s), fmt::make_format_args(ts...));
}

Again, the error only occurs when I use the version I built rather than the one Homebrew provides. The error is as follows:

src/util/log.cpp:13:43: error: no matching function for call to 'make_format_args'
                                          fmt::make_format_args(level_name, f, line, func, msg,
                                          ^~~~~~~~~~~~~~~~~~~~~
lib/fmt/include/fmt/core.h:1804:16: note: candidate function [with Context = fmt::basic_format_context<fmt::appender, char>, T = <const std::string, std::string, unsigned long, const std::string, const std::string, const char *>] not viable: expects an lvalue for 6th argument
constexpr auto make_format_args(T&... args)

I understand the error relates to this question: candidate function not viable: expects an l-value for 3rd argument, but it doesn't make sense to me in this context. It also doesn't make sense because the libfmt API shows this as an example: argument lists. In this example, they are doing the same thing I am.

It doesn't make sense to me that there is an error when I build it myself but not when I use the brew-installed version. It also doesn't make sense that I am getting an error at all, even though I am doing what seems like the same thing as the example in the API. Both the Homebrew version and the manually built version are 10.0.0. Does anyone know what might be wrong?


Solution

  • The error suggests that you are passing an rvalue as the 6th argument (which is cut off in the error message). You don't need fmt::vformat or fmt::make_format_args at all and should be using fmt::format and wrapping the format string in fmt::runtime to mark the format string as only known at runtime:

    return fmt::format(fmt::runtime(format_str),
                       level_name, f, line, func, msg, /* 6th argument */);
    

    This will fix the error and make the intent clear.