I get a very long (300 lines, 3k words) error when trying to use arguments lists containing arguments with a custom formatter. The error in essence is about not finding the right arg_mapper::map instance for the given type.
fmt/core.h:845:47: error: no matching function for call to
'fmt::v6::internal::arg_mapper<...>::map(...)'
Here is my minimal (non)working example:
#include <iostream>
#include <fmt/format.h>
class pow_format {
public:
pow_format(long long val, std::string&& unit, bool binary = false):
val_(val), unit_(unit), binary_(binary) { };
long long val_;
std::string unit_;
bool binary_;
};
namespace fmt {
template <>
struct formatter<pow_format> {
char spec = 0;
template <typename ParseContext>
constexpr auto parse(ParseContext& ctx) -> decltype (ctx.begin()) {
return ctx.begin()
}
template<class FormatContext>
auto format(const pow_format& s, FormatContext &ctx) -> decltype (ctx.out()) {
return format_to(ctx.out(), "{}", s.val_);
}
};
}
int main() {
auto num = pow_format(123456789, "pow");
auto num_arg = fmt::arg("num", num);
auto args = fmt::make_format_args(num_arg);
std::cout << fmt::format("{num}", args) << std::endl;
return 0;
}
fmt::format doesn't take a type-erased list of arguments (fmt::basic_format_args or fmt::format_arg_store, return value of fmt::make_format_args), but a variadic pack of arguments.
fmt::format("{num} {num2}", fmt:::arg("num", num), fmt::arg("num2", num2));
You could use fmt::vformat directly as well, although I don't really see the benefit of it
// equivalent to the snippet above
auto args = fmt::make_format_args(fmt::arg("num", num), fmt::arg("num2", num2));
fmt::vformat("{num} {num2}", {args});
Doh :man_facepalming:, thanks for this.
The point is that we sometimes have to format multiple strings with the same set of arguments. It looks more efficient to do it with a single set.
Seems that this approach is prone to segfaults and such due to the references taken... I wonder it there exists examples of code reusing the same arguments set somewhere.
I don't think you'll save much by reusing the argument store because it's very cheap to construct, but if you do make sure that all the arguments outlive it. It is not recommended and there are no examples.
Well, it is not that much about saving time, but saving screen size and avoiding copy/pasting code all over the place.
See for example https://github.com/Alexays/Waybar/blob/b3f9425d70c0b22e52e9ab1756cf25e1d2f78164/src/modules/network.cpp#L266-L311
Named arguments are tricky. There is no good API for reusing argument lists with them but there are plans to add one: #1170.
I must admit I do not understand everything that is happening here, especially with compile time evaluated parts and constexprs. I indeed got the idea that something tricky was happening. When this gets implemented, it will simplify waybar a lot ;-)
Anyway, I was quite impressed by this library. Thanks for the good work !