This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

4221. Cannot format const-iterable only ranges

Section: 28.5.7 [format.range] Status: New Submitter: Hewill Kang Opened: 2025-03-06 Last modified: 2025-03-09

Priority: Not Prioritized

View all issues with New status.

Discussion:

The standard does not explicitly prohibit ranges that are only const-iterable, i.e. a range with const begin() and deleted or invalid non-const begin().

Unfortunately, those ranges cannot be formatted because the R in formatter<R> is always without the const-qualifier, which makes it never satisfy the range concept (demo):

#include <print>
#include <ranges>

struct R {
  int* begin() = delete;
  int* end() = delete;
  const int* begin() const;
  const int* end() const;
};

int main() {
  const R r;
  static_assert(std::ranges::contiguous_range<decltype(r)>);

  for (auto&& elem : r)
    std::print("{} ", elem); // ok

  std::ranges::for_each(
    r, [](auto&& elem) { std::print("{} ", elem); }
  );                         // ok

  std::print("{}", r);       // not ok
}

Although such type might be relatively rare, it does reflect an inconsistency in the general usage of formatting ranges, which do not support all valid ranges.

Proposed resolution: