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

huangapple go评论63阅读模式
英文:

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

问题

我目前正在使用C++的libfmt库,但我遇到了一个我认为不应该出现的错误。代码有时候能够工作,但有时候不能。

当我从homebrew安装的位置链接libfmt(我在MacOS上),它完全正常工作。当我从我自己构建的位置静态链接时,使用cd $(PATH_FMT) && mkdir -p build && cd build && cmake .. && make。然后我链接的时候用了LDFLAGS += $(PATH_FMT)/build/libfmt.a。两者之间的区别在于我的makefile中是否注释了以下行:CCFLAGS += -I/opt/homebrew/include。代码如下:

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

再次强调,只有在我使用我自己构建的版本而不是Homebrew提供的版本时才会出现错误。错误如下:

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 *&gt;] not viable: expects an lvalue for 6th argument
constexpr auto make_format_args(T&... args)

我理解这个错误与这个问题有关:candidate function not viable: expects an l-value for 3rd argument,但在这种情况下对我来说没有意义。这也不合理,因为libfmt API将其作为示例展示:argument lists。在这个示例中,他们做的与我所做的一样。

对我来说,当我自己构建它时出现错误,但当我使用brew安装的版本时却没有错误,这是毫无道理的。对我来说,即使我做的事情看起来和API中的示例相似,但我仍然无法理解为什么会出错。Homebrew版本和手动构建版本都是10.0.0。有没有人知道可能出了什么问题?

英文:

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) &amp;&amp; mkdir -p build &amp;&amp; cd build &amp;&amp; cmake .. &amp;&amp; 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 &lt;fmt/core.h&gt;
#include &lt;fmt/format.h&gt;

.
.
.

template&lt;typename... Ts&gt; static inline std::string format(const std::string &amp;s, Ts &amp;&amp;...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 &#39;make_format_args&#39;
                                          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&lt;fmt::appender, char&gt;, T = &lt;const std::string, std::string, unsigned long, const std::string, const std::string, const char *&gt;] not viable: expects an lvalue for 6th argument
constexpr auto make_format_args(T&amp;... 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?

答案1

得分: 1

错误提示表明您将一个rvalue作为第6个参数传递(在错误消息中被截断)。您不需要使用 fmt::vformatfmt::make_format_args,而应该使用 fmt::format,并将格式字符串包装在 fmt::runtime 中,以将格式字符串标记为仅在运行时知道:

return fmt::format(fmt::runtime(format_str),
                   level_name, f, line, func, msg, /* 第6个参数 */);

这将修复错误并使意图清晰明确。

英文:

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.

huangapple
  • 本文由 发表于 2023年6月1日 13:20:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76378855.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定