diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h index b73fc121e0f..02561ee63f9 100644 --- a/libstdc++-v3/include/bits/ranges_util.h +++ b/libstdc++-v3/include/bits/ranges_util.h @@ -205,15 +205,18 @@ namespace ranges _It _M_begin = _It(); [[no_unique_address]] _Sent _M_end = _Sent(); + using __size_type + = __detail::__make_unsigned_like_t>; + template struct _Size { }; template struct _Size<_Tp, true> - { __detail::__make_unsigned_like_t<_Tp> _M_size; }; + { _Tp _M_size; }; - [[no_unique_address]] _Size> _M_size = {}; + [[no_unique_address]] _Size<__size_type> _M_size = {}; public: subrange() = default; @@ -226,12 +229,10 @@ namespace ranges constexpr subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s, - __detail::__make_unsigned_like_t> __n) + __size_type __n) requires (_Kind == subrange_kind::sized) : _M_begin(std::move(__i)), _M_end(__s) { - using __detail::__to_unsigned_like; - __glibcxx_assert(__n == __to_unsigned_like(ranges::distance(__i, __s))); if constexpr (_S_store_size) _M_size._M_size = __n; } @@ -258,8 +259,7 @@ namespace ranges requires __detail::__convertible_to_non_slicing, _It> && convertible_to, _Sent> constexpr - subrange(_Rng&& __r, - __detail::__make_unsigned_like_t> __n) + subrange(_Rng&& __r, __size_type __n) requires (_Kind == subrange_kind::sized) : subrange{ranges::begin(__r), ranges::end(__r), __n} { } @@ -267,9 +267,9 @@ namespace ranges template<__detail::__not_same_as _PairLike> requires __detail::__pair_like_convertible_from<_PairLike, const _It&, const _Sent&> - constexpr - operator _PairLike() const - { return _PairLike(_M_begin, _M_end); } + constexpr + operator _PairLike() const + { return _PairLike(_M_begin, _M_end); } constexpr _It begin() const requires copyable<_It> @@ -283,7 +283,7 @@ namespace ranges constexpr bool empty() const { return _M_begin == _M_end; } - constexpr __detail::__make_unsigned_like_t> + constexpr __size_type size() const requires (_Kind == subrange_kind::sized) { if constexpr (_S_store_size) diff --git a/libstdc++-v3/testsuite/std/ranges/subrange/constexpr.cc b/libstdc++-v3/testsuite/std/ranges/subrange/constexpr.cc new file mode 100644 index 00000000000..f5bc52bef84 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/subrange/constexpr.cc @@ -0,0 +1,26 @@ +// { dg-options "-std=gnu++20" } +// { dg-do compile { target c++20 } } + +#include + +struct iterator +{ + using difference_type = int; + + int i; + + int operator*() const { return i; } + + // These are intentionally not constexpr: + iterator& operator++() { ++i; return *this; } + iterator operator++(int) { return {i++}; } + bool operator==(const iterator& it) const { return i == it.i; } +}; + +constexpr iterator begin(1), end(2); + +using std::ranges::subrange; +using std::ranges::subrange_kind; + +// This used to fail due to using operator++ and operator== in an assertion: +constexpr subrange s(begin, end, 1);