A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://stackoverflow.com/questions/77637232/format-as-use-with-range-types below:

c++ - `format_as` use with range types

@康桓瑋 mentioned in a comment that this may be a bug of fmt. The following analysis is purely about why it doesn't work currently, regardless of whether it is a bug or not.

If we use clang 17 to compile the code we can see the following error message

    /opt/compiler-explorer/libs/fmt/10.1.1/include/fmt/format.h:4061:18: error: no matching member function for call to 'format'
     4061 |     return base::format(format_as(value), ctx);
          |            ~~~~~~^~~~~~
    /opt/compiler-explorer/libs/fmt/10.1.1/include/fmt/core.h:1308:22: note: in instantiation of function template specialization 'fmt::formatter<CodecMask>::format<fmt::basic_format_context<fmt::appender, char>>' requested here
     1308 |     ctx.advance_to(f.format(*static_cast<qualified_type*>(arg), ctx));
          |                      ^
    /opt/compiler-explorer/libs/fmt/10.1.1/include/fmt/core.h:1291:21: note: in instantiation of function template specialization 'fmt::detail::value<fmt::basic_format_context<fmt::appender, char>>::format_custom_arg<CodecMask, fmt::formatter<CodecMask>>' requested here
     1291 |     custom.format = format_custom_arg<
          |                     ^
    /opt/compiler-explorer/libs/fmt/10.1.1/include/fmt/core.h:2903:37: note: in instantiation of function template specialization 'fmt::format<CodecMask &>' requested here
     2903 |   return fmt::print(f, "{}\n", fmt::format(fmt, std::forward<T>(args)...));
          |                                     ^
    /opt/compiler-explorer/libs/fmt/10.1.1/include/fmt/core.h:2912:15: note: in instantiation of function template specialization 'fmt::println<CodecMask &>' requested here
     2912 |   return fmt::println(stdout, fmt, std::forward<T>(args)...);
          |               ^
    <source>:68:10: note: in instantiation of function template specialization 'fmt::println<CodecMask &>' requested here
       68 |     fmt::println("mask: {}", mask);
          |          ^
    /opt/compiler-explorer/libs/fmt/10.1.1/include/fmt/ranges.h:546:8: note: candidate function template not viable: expects an lvalue for 1st argument
      546 |   auto format(range_type& range, FormatContext& ctx) const
          |        ^      ~~~~~~~~~~~~~~~~~

That means the issue is that base::format is expecting a range_type& as its first argument, but we have provided a rvalue. Indeed, the function format_as is actually returning a rvalue. Usually, it should just work fine for rvalue if range_type is const T for some T. This is handled by the following lines around line 412 in ranges.h:

template <typename R>
using maybe_const_range =
    conditional_t<has_const_begin_end<R>::value, const R, R>;

Where has_const_begin_end is defined as

template <typename T>
struct has_const_begin_end<
    T,
    void_t<
        decltype(detail::range_begin(std::declval<const remove_cvref_t<T>&>())),
        decltype(detail::range_end(std::declval<const remove_cvref_t<T>&>()))>>
    : std::true_type {};

We may roughly consider the detail::range_begin and detail::range_end as equivalent to std::ranges::begin and std::ranges::end. This is at least true for views. So the real issue is that the filter_view is not const-iterable (Thanks to @cpplearner for correcting in the comments), and the reason for that is explained in this answer (also by @cpplearner).

Now, none of this matters if we pass the view directly to fmt::format or fmt::println, because the correct constructor for fmt::format_arg will be called for our arguments, and that will handle both lvalues and rvalues correctly.

The solution is already pointed out in a comment: collect them in a vector before you return.

auto format_as(CodecMask m) {
    return std::ranges::to<std::vector>(CodecMask::k_codecs | std::views::filter([&](auto c) { return m.has(c); }));
}

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4