Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<format>: in_range apply on non-integrals triggers a static_assert #5182

Open
hewillk opened this issue Dec 11, 2024 · 2 comments · May be fixed by #5187
Open

<format>: in_range apply on non-integrals triggers a static_assert #5182

hewillk opened this issue Dec 11, 2024 · 2 comments · May be fixed by #5187
Labels
bug Something isn't working format C++20/23 format ranges C++20/23 ranges

Comments

@hewillk
Copy link
Contributor

hewillk commented Dec 11, 2024

Yap, another annoying difference-type issue.

STL/stl/inc/format

Lines 3283 to 3290 in 89ca073

template <class _CharT, _RANGES input_range _Range, class _FormatContext>
void _Range_formatter_format_as_string(_Range&& _Rng, _FormatContext& _Ctx, const bool _Debug) {
if constexpr (_RANGES contiguous_range<_Range>) {
const auto _Size = _STD _To_unsigned_like(_RANGES distance(_Rng));
if (!_STD in_range<size_t>(_Size)) [[unlikely]] {
_Throw_format_error("Formatted range is too long.");
}

_Size may be of integer-class type such as _Signed128, which currently does not work with in_range as it Mandates standard or extended integer types:

#include <ranges>
#include <print>

struct ContiguousIter {
  using iterator_category = std::contiguous_iterator_tag;
  using difference_type = std::_Signed128;
  using element_type = char;
  element_type& operator*() const;
  ContiguousIter& operator++();
  ContiguousIter operator++(int);
  ContiguousIter& operator--();
  ContiguousIter operator--(int);
  ContiguousIter& operator+=(difference_type);
  ContiguousIter& operator-=(difference_type);
  element_type* operator->() const;
  element_type& operator[](difference_type) const;
  friend ContiguousIter operator+(ContiguousIter, difference_type);
  friend ContiguousIter operator+(difference_type, ContiguousIter);
  friend ContiguousIter operator-(ContiguousIter, difference_type);
  friend difference_type operator-(ContiguousIter, ContiguousIter);
  auto operator<=>(const ContiguousIter&) const = default;
};

int main() {
  ContiguousIter it;
  std::ranges::contiguous_range auto r = std::ranges::subrange(it, it + 42);
  std::println("{:s}", r); // fire
}

Note that this is not reproducible on Godbolt as the STL version used by MSVC does not yet support formatting ranges. (Is there any way to reproduce this online?)

@frederick-vs-ja
Copy link
Contributor

frederick-vs-ja commented Dec 11, 2024

Actually, I don't think a contiguous_range can have size not representable in size_t. The contiguity of a range is defined via pointer arithmetic, which relies on array objects, so a contiguous range is empty, denotes contiguous array elements, or denotes a single non-array-element object.

Since the object model of C++ doesn't allow arrays of more than SIZE_MAX elements, I think this branch is essentially dead.

Edit: It seems that one might pass an invalid range of illegally huge size, which is UB. Perhaps we can catch this in debug modes.

@hewillk
Copy link
Contributor Author

hewillk commented Dec 12, 2024

Actually, I don't think a contiguous_range can have size not representable in size_t. The contiguity of a range is defined via pointer arithmetic, which relies on array objects, so a contiguous range is empty, denotes contiguous array elements, or denotes a single non-array-element object.

Agreed. It seems reasonable that contiguous_range requires that the difference_type must be ptrdiff_t or at least the same width as ptrdiff_t. Although current standards do not require this.

@CaseyCarter CaseyCarter added bug Something isn't working ranges C++20/23 ranges format C++20/23 format labels Dec 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working format C++20/23 format ranges C++20/23 ranges
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants