Commit bac66329 by Jonathan Wakely Committed by Jonathan Wakely

Revert r278363 "Start work on <ranges> header"

This was not meant to be on the branch I committed r278364 from, as it
is not ready to commit yet.

	* include/std/ranges: Revert accidentally committed changes.

From-SVN: r278365
parent 74533764
2019-11-16 Jonathan Wakely <jwakely@redhat.com>
* include/std/ranges: Revert accidentally committed changes.
* include/std/thread (jthread::jthread()): Use nostopstate constant.
(jthread::jthread(Callable&&, Args&&...)): Use helper function to
create std::thread instead of indirection through a lambda. Use
......
......@@ -38,11 +38,7 @@
#if __cpp_lib_concepts
// #include <compare>
#include <initializer_list>
#include <iterator>
#include <limits>
#include <optional>
/**
* @defgroup ranges Ranges
......@@ -52,30 +48,7 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
namespace __debug
{
template<typename _Key, typename _Cmp, typename _Allocator> class set;
template<typename _Key, typename _Cmp, typename _Allocator> class multiset;
template<typename _Key, typename _Hash, typename _Pred, typename _Allocator>
class unordered_set;
template<typename _Key, typename _Hash, typename _Pred, typename _Allocator>
class unordered_multiset;
} // namespace __debug
_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Key, typename _Cmp, typename _Allocator> class set;
template<typename _Key, typename _Cmp, typename _Allocator> class multiset;
template<typename _Key, typename _Hash, typename _Pred, typename _Allocator>
class unordered_set;
template<typename _Key, typename _Hash, typename _Pred, typename _Allocator>
class unordered_multiset;
_GLIBCXX_END_NAMESPACE_CONTAINER
template<typename _It, typename _Alloc>
class match_results;
namespace ranges
{
// [range.range] The range concept.
......@@ -95,12 +68,6 @@ namespace ranges
using range_rvalue_reference_t
= iter_rvalue_reference_t<iterator_t<_Range>>;
namespace __detail
{
template<typename _Tp>
concept __forwarding_range = range<_Tp> && __range_impl<_Tp>;
} // namespace __detail
// [range.sized] The sized_range concept.
// Defined in <bits/range_iterator.h>
// template<typename> concept sized_range;
......@@ -137,1283 +104,6 @@ namespace ranges
template<typename _Tp>
concept common_range
= range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp>>;
struct view_base { };
namespace __detail
{
template<typename _Tp, template<typename...> class _Tmpl>
struct __is_specialization_of
: false_type {};
template<template<typename...> class _Tmpl, typename... _Args>
struct __is_specialization_of<_Tmpl<_Args...>, _Tmpl>
: true_type { };
template<typename _Tp>
concept __set_like
= __is_specialization_of<_Tp, _GLIBCXX_STD_C::set>()
|| __is_specialization_of<_Tp, _GLIBCXX_STD_C::multiset>()
|| __is_specialization_of<_Tp, _GLIBCXX_STD_C::unordered_set>()
|| __is_specialization_of<_Tp, _GLIBCXX_STD_C::unordered_multiset>()
|| __is_specialization_of<_Tp, std::__debug::set>()
|| __is_specialization_of<_Tp, std::__debug::multiset>()
|| __is_specialization_of<_Tp, std::__debug::unordered_set>()
|| __is_specialization_of<_Tp, std::__debug::unordered_multiset>();
template<typename _Tp>
concept __deep_const_range = range<_Tp> && range<const _Tp>
&& same_as<range_reference_t<_Tp>, range_reference_t<const _Tp>>;
template<typename _Tp>
inline constexpr bool __enable_view_impl = derived_from<_Tp, view_base>
|| (!__set_like<_Tp> && !__deep_const_range<_Tp>);
template<typename _Tp>
inline constexpr bool __enable_view_impl<std::initializer_list<_Tp>>
= false;
template<typename _It, typename _Alloc>
inline constexpr bool __enable_view_impl<std::match_results<_It, _Alloc>>
= false;
} // namespace __detail
template<typename _Tp>
inline constexpr bool enable_view
= __detail::__enable_view_impl<remove_cv_t<_Tp>>;
template<typename _Tp>
concept view = range<_Tp> && semiregular<_Tp> && enable_view<_Tp>;
template<typename _Tp>
concept viewable_range = range<_Tp>
&& (__detail::__forwarding_range<_Tp> || view<decay_t<_Tp>>);
namespace __detail
{
template<typename _Range>
concept __simple_view = view<_Range> && range<const _Range>
&& same_as<iterator_t<_Range>, iterator_t<const _Range>>
&& same_as<sentinel_t<_Range>, sentinel_t<const _Range>>;
template<typename _It>
concept __has_arrow = input_iterator<_It>
&& (is_pointer_v<_It> || requires(_It __it) { __it.operator->(); });
template<typename _Tp, typename _Up>
concept __not_same_as
= !same_as<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>;
} // namespace __detail
template<typename _Derived>
requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
class view_interface : public view_base
{
private:
constexpr _Derived& _M_derived() noexcept
{
static_assert(derived_from<_Derived, view_interface<_Derived>>);
static_assert(view<_Derived>);
return static_cast<_Derived&>(*this);
}
constexpr const _Derived& _M_derived() const noexcept
{
static_assert(derived_from<_Derived, view_interface<_Derived>>);
static_assert(view<_Derived>);
return static_cast<const _Derived&>(*this);
}
public:
constexpr bool
empty() requires forward_range<_Derived>
{ return ranges::begin(_M_derived()) == ranges::end(_M_derived()); }
constexpr bool
empty() const requires forward_range<const _Derived>
{ return ranges::begin(_M_derived()) == ranges::end(_M_derived()); }
constexpr explicit
operator bool() requires requires { ranges::empty(_M_derived()); }
{ return !ranges::empty(_M_derived()); }
constexpr explicit
operator bool() const requires requires { ranges::empty(_M_derived()); }
{ return !ranges::empty(_M_derived()); }
constexpr auto
data() requires contiguous_iterator<iterator_t<_Derived>>
{ return to_address(ranges::begin(_M_derived())); }
constexpr auto
data() const
requires range<const _Derived>
&& contiguous_iterator<iterator_t<const _Derived>>
{ return to_address(ranges::begin(_M_derived())); }
constexpr auto
size()
requires forward_range<_Derived>
&& sized_sentinel_for<sentinel_t<_Derived>, iterator_t<_Derived>>
{ return ranges::end(_M_derived()) - ranges::begin(_M_derived()); }
constexpr auto
size() const
requires forward_range<const _Derived>
&& sized_sentinel_for<sentinel_t<const _Derived>,
iterator_t<const _Derived>>
{ return ranges::end(_M_derived()) - ranges::begin(_M_derived()); }
constexpr decltype(auto)
front() requires forward_range<_Derived>
{
__glibcxx_assert(!empty());
return *ranges::begin(_M_derived());
}
constexpr decltype(auto)
front() const requires forward_range<const _Derived>
{
__glibcxx_assert(!empty());
return *ranges::begin(_M_derived());
}
constexpr decltype(auto)
back()
requires bidirectional_range<_Derived> && common_range<_Derived>
{
__glibcxx_assert(!empty());
return *ranges::prev(ranges::end(_M_derived()));
}
constexpr decltype(auto)
back() const
requires bidirectional_range<const _Derived>
&& common_range<const _Derived>
{
__glibcxx_assert(!empty());
return *ranges::prev(ranges::end(_M_derived()));
}
template<random_access_range _Range = _Derived>
constexpr decltype(auto)
operator[](range_difference_t<_Range> __n)
{ return ranges::begin(_M_derived())[__n]; }
template<random_access_range _Range = const _Derived>
constexpr decltype(auto)
operator[](range_difference_t<_Range> __n) const
{ return ranges::begin(_M_derived())[__n]; }
};
namespace __detail
{
template<typename _Tp>
concept __pair_like
= !is_reference_v<_Tp> && requires(_Tp __t)
{
typename tuple_size<_Tp>::type;
requires derived_from<tuple_size<_Tp>, integral_constant<size_t, 2>>;
typename tuple_element_t<0, remove_const_t<_Tp>>;
typename tuple_element_t<1, remove_const_t<_Tp>>;
{ get<0>(__t) } -> convertible_to<const tuple_element_t<0, _Tp>&>;
{ get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Tp>&>;
};
template<typename _Tp, typename _Up, typename _Vp>
concept __pair_like_convertible_to
= !range<_Tp> && __pair_like<remove_reference_t<_Tp>>
&& requires(_Tp&& __t)
{
{ get<0>(std::forward<_Tp>(__t)) } -> convertible_to<_Up>;
{ get<1>(std::forward<_Tp>(__t)) } -> convertible_to<_Vp>;
};
template<typename _Tp, typename _Up, typename _Vp>
concept __pair_like_convertible_from
= !range<_Tp> && __pair_like<_Tp>
&& constructible_from<_Tp, _Up, _Vp>;
template<typename _Tp>
concept __iterator_sentinel_pair
= !range<_Tp> && __pair_like<_Tp>
&& sentinel_for<tuple_element_t<1, _Tp>, tuple_element_t<0, _Tp>>;
template<typename _Tp, bool _MaxDiff = same_as<_Tp, __max_diff_type>>
using __make_unsigned_like_t
= conditional_t<_MaxDiff, __max_size_type, make_unsigned_t<_Tp>>;
} // namespace __detail
enum class subrange_kind : bool { unsized, sized };
template<input_or_output_iterator _It, sentinel_for<_It> _Sent = _It,
subrange_kind _Kind = sized_sentinel_for<_Sent, _It>
? subrange_kind::sized : subrange_kind::unsized>
requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _It>)
class subrange : public view_interface<subrange<_It, _Sent, _Kind>>
{
private:
static constexpr bool _S_store_size
= _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _It>;
_It _M_begin = _It();
_Sent _M_end = _Sent();
template<typename, bool = _S_store_size>
struct _Size
{ };
template<typename _Tp>
struct _Size<_Tp, true>
{ __detail::__make_unsigned_like_t<_Tp> _M_size; };
[[no_unique_address]] _Size<iter_difference_t<_It>> _M_size = {};
public:
subrange() = default;
constexpr
subrange(_It __i, _Sent __s) requires (!_S_store_size)
: _M_begin(__i), _M_end(__s)
{ }
constexpr
subrange(_It __i, _Sent __s,
__detail::__make_unsigned_like_t<iter_difference_t<_It>> __n)
requires (_Kind == subrange_kind::sized)
: _M_begin(__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;
}
template<__detail::__not_same_as<subrange> _Rng>
requires __detail::__forwarding_range<_Rng>
&& convertible_to<iterator_t<_Rng>, _It>
&& convertible_to<sentinel_t<_Rng>, _Sent>
constexpr
subrange(_Rng&& __r) requires (!_S_store_size || sized_range<_Rng>)
: subrange{ranges::begin(__r), ranges::end(__r)}
{
if constexpr (_S_store_size)
_M_size._M_size = ranges::size(__r);
}
template<__detail::__forwarding_range _Rng>
requires convertible_to<iterator_t<_Rng>, _It>
&& convertible_to<sentinel_t<_Rng>, _Sent>
constexpr
subrange(_Rng&& __r,
__detail::__make_unsigned_like_t<iter_difference_t<_It>> __n)
requires (_Kind == subrange_kind::sized)
: subrange{ranges::begin(__r), ranges::end(__r), __n}
{ }
template<__detail::__not_same_as<subrange> _PairLike>
requires __detail::__pair_like_convertible_to<_PairLike, _It, _Sent>
constexpr
subrange(_PairLike&& __r) requires (!_S_store_size)
: subrange{std::get<0>(std::forward<_PairLike>(__r)),
std::get<1>(std::forward<_PairLike>(__r))}
{ }
template<__detail::__pair_like_convertible_to<_It, _Sent> _PairLike>
constexpr
subrange(_PairLike&& __r,
__detail::__make_unsigned_like_t<iter_difference_t<_It>> __n)
requires (_Kind == subrange_kind::sized)
: subrange{std::get<0>(std::forward<_PairLike>(__r)),
std::get<1>(std::forward<_PairLike>(__r)), __n}
{ }
template<__detail::__not_same_as<subrange> _PairLike>
requires __detail::__pair_like_convertible_from<_PairLike, const _It&,
const _Sent&>
constexpr
operator _PairLike() const
{ return _PairLike(_M_begin, _M_end); }
constexpr _It begin() const { return _M_begin; }
constexpr _Sent end() const { return _M_end; }
constexpr bool empty() const { return _M_begin == _M_end; }
constexpr __detail::__make_unsigned_like_t<iter_difference_t<_It>>
size() const requires (_Kind == subrange_kind::sized)
{
if constexpr (_S_store_size)
return _M_size._M_size;
else
return __detail::__to_unsigned_like(_M_end - _M_begin);
}
[[nodiscard]] constexpr subrange
next(iter_difference_t<_It> __n = 1) const
{
auto __tmp = *this;
__tmp.advance(__n);
return __tmp;
}
[[nodiscard]] constexpr subrange
prev(iter_difference_t<_It> __n = 1) const
requires bidirectional_iterator<_It>
{
auto __tmp = *this;
__tmp.advance(--__n);
return __tmp;
}
constexpr subrange&
advance(iter_difference_t<_It> __n)
{
if constexpr (_S_store_size)
{
auto __d = __n - ranges::advance(_M_begin, __n, _M_end);
if (__d >= 0)
_M_size._M_size -= __detail::__to_unsigned_like(__d);
else
_M_size._M_size += __detail::__to_unsigned_like(-__d);
}
else
ranges::advance(_M_begin, __n, _M_end);
return *this;
}
friend constexpr _It
begin(subrange&& __r) { return __r.begin(); }
friend constexpr _Sent
end(subrange&& __r) { return __r.end(); }
};
template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
subrange(_It, _Sent,
__detail::__make_unsigned_like_t<iter_difference_t<_It>>)
-> subrange<_It, _Sent, subrange_kind::sized>;
template<__detail::__iterator_sentinel_pair _Pr>
subrange(_Pr)
-> subrange<tuple_element_t<0, _Pr>, tuple_element_t<1, _Pr>>;
template<__detail::__iterator_sentinel_pair _Pr>
subrange(_Pr, __detail::__make_unsigned_like_t<iter_difference_t<
tuple_element_t<0, _Pr>>>)
-> subrange<tuple_element_t<0, _Pr>, tuple_element_t<1, _Pr>,
subrange_kind::sized>;
template<__detail::__forwarding_range _Rng>
subrange(_Rng&&)
-> subrange<iterator_t<_Rng>, sentinel_t<_Rng>,
(sized_range<_Rng>
|| sized_sentinel_for<sentinel_t<_Rng>, iterator_t<_Rng>>)
? subrange_kind::sized : subrange_kind::unsized>;
template<__detail::__forwarding_range _Rng>
subrange(_Rng&&,
__detail::__make_unsigned_like_t<range_difference_t<_Rng>>)
-> subrange<iterator_t<_Rng>, sentinel_t<_Rng>, subrange_kind::sized>;
template<size_t _Num, class _It, class _Sent, subrange_kind _Kind>
requires (_Num < 2)
constexpr auto
get(const subrange<_It, _Sent, _Kind>& __r)
{
if constexpr (_Num == 0)
return __r.begin();
else
return __r.end();
}
} // namespace ranges
using ranges::get;
namespace ranges
{
/// Type returned by algorithms instead of a dangling iterator or subrange.
struct dangling
{
constexpr dangling() noexcept = default;
template<typename... _Args>
constexpr dangling(_Args&&...) noexcept { }
};
template<typename _Tp> requires is_object_v<_Tp>
class empty_view : public view_interface<empty_view<_Tp>>
{
public:
static constexpr _Tp* begin() noexcept { return nullptr; }
static constexpr _Tp* end() noexcept { return nullptr; }
static constexpr _Tp* data() noexcept { return nullptr; }
static constexpr size_t size() noexcept { return 0; }
static constexpr bool empty() noexcept { return true; }
friend constexpr _Tp* begin(empty_view) noexcept { return nullptr; }
friend constexpr _Tp* end(empty_view) noexcept { return nullptr; }
};
namespace __detail
{
template<copy_constructible _Tp> requires is_object_v<_Tp>
struct __box : std::optional<_Tp>
{
using std::optional<_Tp>::optional;
constexpr
__box()
noexcept(is_nothrow_default_constructible_v<_Tp>)
requires default_constructible<_Tp>
: std::optional<_Tp>{std::in_place}
{ }
using std::optional<_Tp>::operator=;
__box&
operator=(const __box& __that)
noexcept(is_nothrow_copy_constructible_v<_Tp>)
requires (!assignable_from<_Tp&, const _Tp&>)
{
if ((bool)__that)
this->emplace(*__that);
else
this->reset();
return *this;
}
__box&
operator=(__box&& __that)
noexcept(is_nothrow_move_constructible_v<_Tp>)
requires (!assignable_from<_Tp&, _Tp>)
{
if ((bool)__that)
this->emplace(std::move(*__that));
else
this->reset();
return *this;
}
};
} // namespace __detail
/// A view that contains exactly one element.
template<copy_constructible _Tp> requires is_object_v<_Tp>
class single_view : public view_interface<single_view<_Tp>>
{
public:
single_view() = default;
constexpr explicit
single_view(const _Tp& __t)
: _M_value(__t)
{ }
constexpr explicit
single_view(_Tp&& __t)
: _M_value(std::move(__t))
{ }
template<typename... _Args>
requires constructible_from<_Tp, _Args...>
constexpr
single_view(in_place_t, _Args&&... __args)
: _M_value{in_place, std::forward<_Args>(__args)...}
{ }
constexpr _Tp*
begin() noexcept
{ return data(); }
constexpr const _Tp*
begin() const noexcept
{ return data(); }
constexpr _Tp*
end() noexcept
{ return data() + 1; }
constexpr const _Tp*
end() const noexcept
{ return data() + 1; }
static constexpr size_t
size() noexcept
{ return 1; }
constexpr _Tp*
data() noexcept
{ return _M_value.operator->(); }
constexpr const _Tp*
data() const noexcept
{ return _M_value.operator->(); }
private:
__detail::__box<_Tp> _M_value;
};
namespace __detail
{
#ifdef _GLIBCXX_INTEGER_LIKE_TYPES
class __max_diff_type
{
public:
__max_diff_type() = default;
template<signed_integral _Tp>
constexpr
__max_diff_type(_Tp __i) noexcept
: _M_val(__i < 0 ? rep(~__i) + rep(1) : __i), _M_sign_bit(__i < 0)
{ }
template<unsigned_integral _Tp>
constexpr
__max_diff_type(_Tp __i) noexcept
: _M_val(__i), _M_sign_bit(false)
{ }
template<signed_integral _Tp>
constexpr explicit operator _Tp() const noexcept
{
_Tp __val = _M_val % (sizeof(_Tp) * __CHAR_BIT__);
if (_M_sign_bit)
return -__val;
else
return __val;
}
template<unsigned_integral _Tp>
constexpr explicit operator _Tp() const noexcept
{ return _M_val; }
constexpr explicit
operator bool() const noexcept { return _M_val != 0; }
constexpr __max_diff_type
operator+() const noexcept { return *this; }
constexpr __max_diff_type
operator-() const noexcept
{ return __max_diff_type{_M_val, !_M_sign_bit}; }
constexpr __max_diff_type
operator~() const noexcept
{ return __max_diff_type{~_M_val, !_M_sign_bit}; }
constexpr __max_diff_type&
operator+=(const __max_diff_type& __r) noexcept
{
if (_M_sign_bit == __r._M_sign_bit)
_M_val += __r._M_val;
else if (_M_val >= __r._M_val)
_M_val -= __r._M_val;
else
{
_M_val = __r._M_val - _M_val;
_M_sign_bit = !_M_sign_bit;
}
return *this;
}
constexpr __max_diff_type&
operator-=(const __max_diff_type& __r) noexcept
{
auto __rneg = __r;
__rneg._M_sign_bit = !__r._M_sign_bit;
return *this += __rneg;
}
constexpr __max_diff_type&
operator*=(const __max_diff_type& __r) noexcept
{
_M_val *= __r._M_val;
_M_sign_bit = (_M_sign_bit != __r._M_sign_bit);
return *this;
}
constexpr __max_diff_type&
operator/=(const __max_diff_type& __r) noexcept
{
_M_val /= __r._M_val;
_M_sign_bit = (_M_sign_bit != __r._M_sign_bit);
return *this;
}
constexpr __max_diff_type&
operator%=(const __max_diff_type& __r) noexcept
{
_M_val /= __r._M_val;
return *this;
}
constexpr __max_diff_type&
operator<<=(const __max_diff_type& __r) noexcept
{
__glibcxx_assert(__r._M_val < numeric_limits<rep>::digits);
__glibcxx_assert(!__r._M_sign_bit);
_M_val <<= __r._M_val;
return *this;
}
constexpr __max_diff_type&
operator>>=(const __max_diff_type& __r) noexcept
{
__glibcxx_assert(__r._M_val < numeric_limits<rep>::digits);
__glibcxx_assert(!__r._M_sign_bit);
_M_val >>= __r._M_val;
return *this;
}
friend constexpr __max_diff_type
operator+(__max_diff_type __l, const __max_diff_type& __r) noexcept
{
__l += __r;
return __l;
}
friend constexpr __max_diff_type
operator-(__max_diff_type __l, const __max_diff_type& __r) noexcept
{
__l -= __r;
return __l;
}
friend constexpr __max_diff_type
operator*(__max_diff_type __l, const __max_diff_type& __r) noexcept
{
__l *= __r;
return __l;
}
friend constexpr __max_diff_type
operator/(__max_diff_type __l, const __max_diff_type& __r) noexcept
{
__l /= __r;
return __l;
}
friend constexpr __max_diff_type
operator%(__max_diff_type __l, const __max_diff_type& __r) noexcept
{
__l %= __r;
return __l;
}
friend constexpr __max_diff_type
operator<<(__max_diff_type __l, const __max_diff_type& __r) noexcept
{
__l <<= __r;
return __l;
}
friend constexpr __max_diff_type
operator>>(__max_diff_type __l, const __max_diff_type& __r) noexcept
{
__l >>= __r;
return __l;
}
// TODO & | ^
friend constexpr bool
operator==(const __max_diff_type& __l, const __max_diff_type& __r)
noexcept
{
return __l._M_val == __r._M_val && __l._M_sign_bit == __r._M_sign_bit;
}
friend constexpr bool
operator!=(const __max_diff_type& __l, const __max_diff_type& __r)
noexcept
{ return !(__l == __r); }
friend constexpr bool
operator<(const __max_diff_type& __l, const __max_diff_type& __r)
noexcept
{
if (__l._M_sign_bit)
{
if (__r._M_sign_bit)
return __l._M_val > __r._M_val;
else
return true;
}
else if (__r._M_sign_bit)
return false;
return __l._M_val < __r._M_val;
}
friend constexpr bool
operator>(const __max_diff_type& __l, const __max_diff_type& __r)
noexcept
{ return __r < __l; }
friend constexpr bool
operator<=(const __max_diff_type& __l, const __max_diff_type& __r)
noexcept
{ return !(__r < __l); }
friend constexpr bool
operator>=(const __max_diff_type& __l, const __max_diff_type& __r)
noexcept
{ return !(__l < __r); }
private:
#ifdef __SIZEOF_INT128__
using rep = unsigned __int128;
#else
using rep = unsigned long long;
#endif
rep _M_val = 0;
bool _M_sign_bit = false;
constexpr explicit
__max_diff_type(rep __val, bool __sb) noexcept
: _M_val(__val), _M_sign_bit(__sb)
{ }
friend class __max_size_type;
};
class __max_size_type
{
public:
__max_size_type() = default;
template<integral _Tp>
constexpr
__max_size_type(_Tp __i) noexcept
: _M_val(__i), _M_msb(0)
{ }
constexpr explicit
__max_size_type(const __max_diff_type& __d)
: _M_val(__d._M_val), _M_msb(__d._M_sign_bit)
{ }
template<integral _Tp>
constexpr explicit operator _Tp() const noexcept
{ return _M_val; }
constexpr explicit
operator bool() const noexcept { return _M_val != 0; }
constexpr __max_size_type
operator+() const noexcept { return *this; }
constexpr __max_size_type
operator-() const noexcept
{ return __max_size_type{_M_val, !_M_sign_bit}; }
constexpr __max_size_type
operator~() const noexcept
{ return __max_size_type{~_M_val, !_M_sign_bit}; }
constexpr __max_size_type&
operator+=(const __max_size_type& __r) noexcept
{
if (_M_sign_bit == __r._M_sign_bit)
_M_val += __r._M_val;
else if (_M_val >= __r._M_val)
_M_val -= __r._M_val;
else
{
_M_val = __r._M_val - _M_val;
_M_sign_bit = !_M_sign_bit;
}
return *this;
}
constexpr __max_size_type&
operator-=(const __max_size_type& __r) noexcept
{
auto __rneg = __r;
__rneg._M_sign_bit = !__r._M_sign_bit;
return *this += __rneg;
}
constexpr __max_size_type&
operator*=(const __max_size_type& __r) noexcept
{
_M_val *= __r._M_val;
_M_sign_bit ^= __r._M_sign_bit;
return *this;
}
constexpr __max_size_type&
operator/=(const __max_size_type& __r) noexcept
{
_M_val /= __r._M_val;
_M_sign_bit ^= __r._M_sign_bit;
return *this;
}
constexpr __max_size_type&
operator%=(const __max_size_type& __r) noexcept
{
_M_val /= __r._M_val;
return *this;
}
constexpr __max_size_type&
operator<<=(const __max_size_type& __r) noexcept
{
__glibcxx_assert(__r._M_val < numeric_limits<rep>::digits);
__glibcxx_assert(__r._M_sign_bit == 0);
_M_val <<= __r._M_val;
return *this;
}
constexpr __max_size_type&
operator>>=(const __max_size_type& __r) noexcept
{
__glibcxx_assert(__r._M_val < numeric_limits<rep>::digits);
__glibcxx_assert(__r._M_sign_bit == 0);
_M_val >>= __r._M_val;
return *this;
}
friend constexpr __max_size_type
operator+(__max_size_type __l, const __max_size_type& __r) noexcept
{
__l += __r;
return __l;
}
friend constexpr __max_size_type
operator-(__max_size_type __l, const __max_size_type& __r) noexcept
{
__l -= __r;
return __l;
}
friend constexpr __max_size_type
operator*(__max_size_type __l, const __max_size_type& __r) noexcept
{
__l *= __r;
return __l;
}
friend constexpr __max_size_type
operator/(__max_size_type __l, const __max_size_type& __r) noexcept
{
__l /= __r;
return __l;
}
friend constexpr __max_size_type
operator%(__max_size_type __l, const __max_size_type& __r) noexcept
{
__l %= __r;
return __l;
}
friend constexpr __max_size_type
operator<<(__max_size_type __l, const __max_size_type& __r) noexcept
{
__l <<= __r;
return __l;
}
friend constexpr __max_size_type
operator>>(__max_size_type __l, const __max_size_type& __r) noexcept
{
__l >>= __r;
return __l;
}
// TODO & | ^ > <= >=
friend constexpr bool
operator==(const __max_size_type& __l, const __max_size_type& __r)
noexcept
{
return __l._M_val == __r._M_val && __l._M_msb == __r._M_msb;
}
friend constexpr bool
operator!=(const __max_size_type& __l, const __max_size_type& __r)
noexcept
{ return !(__l == __r); }
friend constexpr bool
operator<(const __max_size_type& __l, const __max_size_type& __r)
noexcept
{
if (__l._M_msb == __r._M_msb)
return __l._M_val < __r._M_val;
else
return __r._M_msb;
}
friend constexpr bool
operator>(const __max_size_type& __l, const __max_size_type& __r)
noexcept
{ return __r < __l; }
private:
#ifdef __SIZEOF_INT128__
using rep = unsigned __int128;
#else
using rep = unsigned long long;
#endif
rep _M_val = 0;
unsigned _M_msb : 1;
constexpr explicit
__max_size_type(rep __val, int __sb) noexcept
: _M_val(__val), _M_sig_bit(__sb)
{ }
};
#endif // _GLIBCXX_NO_INTEGER_LIKE_TYPES
template<typename _Wp>
constexpr auto __to_signed_like(_Wp __w) noexcept
{
if constexpr (!integral<_Wp>)
return iter_difference_t<_Wp>();
else if constexpr (sizeof(iter_difference_t<_Wp>) > sizeof(_Wp))
return iter_difference_t<_Wp>(__w);
else if constexpr (sizeof(ptrdiff_t) > sizeof(_Wp))
return ptrdiff_t(__w);
else if constexpr (sizeof(long long) > sizeof(_Wp))
return (long long)(__w);
#ifdef __SIZEOF_INT128__
else if constexpr (__SIZEOF_INT128__ > sizeof(_Wp))
return __int128(__w);
#endif
else
return __max_diff_type(__w);
}
template<typename _Wp>
using __iota_diff_t = decltype(__to_signed_like(std::declval<_Wp>()));
template<typename _It>
concept __decrementable = incrementable<_It>
&& requires(_It __i)
{
{ --__i } -> same_as<_It&>;
{ __i-- } -> same_as<_It>;
};
template<typename _It>
concept __advanceable = __decrementable<_It> && totally_ordered<_It>
&& requires( _It __i, const _It __j, const __iota_diff_t<_It> __n)
{
{ __i += __n } -> same_as<_It&>;
{ __i -= __n } -> same_as<_It&>;
_It(__j + __n);
_It(__n + __j);
_It(__j - __n);
{ __j - __j } -> convertible_to<__iota_diff_t<_It>>;
};
} // namespace __detail
template<weakly_incrementable _Winc,
semiregular _Bound = unreachable_sentinel_t>
requires std::__detail::__weakly_eq_cmp_with<_Winc, _Bound>
class iota_view : public view_interface<iota_view<_Winc, _Bound>>
{
private:
struct _Iterator
{
private:
static auto
_S_iter_cat()
{
using namespace __detail;
if constexpr (__advanceable<_Winc>)
return random_access_iterator_tag{};
else if constexpr (__decrementable<_Winc>)
return bidirectional_iterator_tag{};
else if constexpr (incrementable<_Winc>)
return forward_iterator_tag{};
else
return input_iterator_tag{};
}
public:
using iterator_category = decltype(_S_iter_cat());
using value_type = _Winc;
using difference_type = __detail::__iota_diff_t<_Winc>;
_Iterator() = default;
constexpr explicit
_Iterator(_Winc __value)
: _M_value(__value) { }
constexpr _Winc
operator*() const noexcept(is_nothrow_copy_constructible_v<_Winc>)
{ return *_M_value; }
constexpr _Iterator&
operator++()
{
++_M_value;
return *this;
}
constexpr void
operator++(int)
{ ++*this; }
constexpr _Iterator
operator++(int) requires incrementable<_Winc>
{
auto __tmp = *this;
++*this;
return __tmp;
}
constexpr _Iterator&
operator--() requires __detail::__decrementable<_Winc>
{
--_M_value;
return *this;
}
constexpr _Iterator
operator--(int) requires __detail::__decrementable<_Winc>
{
auto __tmp = *this;
--*this;
return __tmp;
}
constexpr _Iterator&
operator+=(difference_type __n) requires __detail::__advanceable<_Winc>
{
using namespace __detail;
if constexpr (__is_integer_like<_Winc>
&& !__is_signed_integer_like<_Winc>)
{
if (__n >= difference_type(0))
_M_value += static_cast<_Winc>(__n);
else
_M_value -= static_cast<_Winc>(-__n);
}
else
_M_value += __n;
return *this;
}
constexpr _Iterator&
operator-=(difference_type __n) requires __detail::__advanceable<_Winc>
{
using namespace __detail;
if constexpr (__is_integer_like<_Winc>
&& !__is_signed_integer_like<_Winc>)
{
if (__n >= difference_type(0))
_M_value -= static_cast<_Winc>(__n);
else
_M_value += static_cast<_Winc>(-__n);
}
else
_M_value -= __n;
return *this;
}
constexpr _Winc
operator[](difference_type __n) const
requires __detail::__advanceable<_Winc>
{ return _Winc(_M_value + __n); }
friend constexpr bool
operator==(const _Iterator& __x, const _Iterator& __y)
requires equality_comparable<_Winc>
{ return __x._M_value == __y._M_value; }
friend constexpr bool
operator<(const _Iterator& __x, const _Iterator& __y)
requires totally_ordered<_Winc>
{ return __x._M_value < __y._M_value; }
friend constexpr bool
operator>(const _Iterator& __x, const _Iterator& __y)
requires totally_ordered<_Winc>
{ return __y < __x; }
friend constexpr bool
operator<=(const _Iterator& __x, const _Iterator& __y)
requires totally_ordered<_Winc>
{ return !(__y < __x); }
friend constexpr bool
operator>=(const _Iterator& __x, const _Iterator& __y)
requires totally_ordered<_Winc>
{ return !(__x < __y); }
#ifdef __cpp_lib_threeway_comparison
friend constexpr compare_three_way_result_t<_Winc>
operator<=>(const _Iterator& __x, const _Iterator& __y)
requires totally_ordered<_Winc> && three_way_comparable<_Winc>
{ return __x._M_value <=> __y._M_value; }
#endif
friend constexpr _Iterator
operator+(_Iterator __i, difference_type __n)
requires __detail::__advanceable<_Winc>
{ return __i += __n; }
friend constexpr _Iterator
operator+(difference_type __n, _Iterator __i)
requires __detail::__advanceable<_Winc>
{ return __i += __n; }
friend constexpr _Iterator
operator-(_Iterator __i, difference_type __n)
requires __detail::__advanceable<_Winc>
{ return __i -= __n; }
friend constexpr difference_type
operator-(const _Iterator& __x, const _Iterator& __y)
requires __detail::__advanceable<_Winc>
{
using namespace __detail;
using _Dt = difference_type;
if constexpr (__is_integer_like<_Winc>)
{
if constexpr (__is_signed_integer_like<_Winc>)
return _Dt(_Dt(__x._M_value) - _Dt(__y._M_value));
else
return (__y._M_value > __x._M_value)
? _Dt(-_Dt(__y._M_value - __x._M_value))
: _Dt(__x._M_value - __y._M_value);
}
else
return __x._M_value - __y._M_value;
}
private:
_Winc _M_value = _Winc();
};
struct _Sentinel
{
private:
_Bound _M_bound = _Bound();
public:
_Sentinel() = default;
constexpr explicit
_Sentinel(_Bound __bound)
: _M_bound(__bound) { }
friend constexpr bool
operator==(const _Iterator& __x, const _Sentinel& __y)
{ return __x._M_value == __y._M_bound; }
friend constexpr iter_difference_t<_Winc>
operator-(const _Iterator& __x, const _Sentinel& __y)
requires sized_sentinel_for<_Bound, _Winc>
{ return __x._M_value - __y._M_bound; }
friend constexpr iter_difference_t<_Winc>
operator-(const _Sentinel& __x, const _Iterator& __y)
requires sized_sentinel_for<_Bound, _Winc>
{ return -(__y - __x); }
};
_Winc _M_value = _Winc();
_Bound _M_bound = _Bound();
public:
iota_view() = default;
constexpr explicit
iota_view(_Winc __value)
: _M_value(__value)
{ }
constexpr
iota_view(type_identity_t<_Winc> __value,
type_identity_t<_Bound> __bound)
: _M_value(__value), _M_bound(__bound)
{
if constexpr (totally_ordered_with<_Winc, _Bound>)
__glibcxx_assert( bool(__value <= __bound) );
}
constexpr _Iterator
begin() const { return _Iterator{_M_value}; }
constexpr auto
end() const
{
if constexpr (same_as<_Bound, unreachable_sentinel_t>)
return unreachable_sentinel;
else
return _Sentinel{_M_bound};
}
constexpr _Iterator
end() const requires same_as<_Winc, _Bound>
{ return _Iterator{_M_bound}; }
constexpr auto
size() const
requires (same_as<_Winc, _Bound> && __detail::__advanceable<_Winc>)
|| (integral<_Winc> && integral<_Bound>)
|| sized_sentinel_for<_Bound, _Winc>
{
using namespace __detail;
if constexpr (__is_integer_like<_Winc> && __is_integer_like<_Bound>)
return (_M_value < 0)
? ((_M_bound < 0)
? __to_unsigned_like(-_M_value) - __to_unsigned_like(-_M_bound)
: __to_unsigned_like(_M_bound) + __to_unsigned_like(-_M_value))
: __to_unsigned_like(_M_bound) - __to_unsigned_like(_M_value);
else
return __to_unsigned_like(_M_bound - _M_value);
}
};
template<typename _Winc, typename _Bound>
requires (!__detail::__is_integer_like<_Winc>
|| !__detail::__is_integer_like<_Bound>
|| (__detail::__is_signed_integer_like<_Winc>
== __detail::__is_signed_integer_like<_Bound>))
iota_view(_Winc, _Bound) -> iota_view<_Winc, _Bound>;
namespace views
{
template<typename _Tp>
inline constexpr empty_view<_Tp> empty{};
struct _Single
{
template<typename _Tp>
auto
operator()(_Tp&& __e) const
{ return single_view{std::forward<_Tp>(__e)}; }
};
inline constexpr _Single single{};
struct _Iota
{
template<typename _Tp>
auto
operator()(_Tp&& __e) const
{ return iota_view{std::forward<_Tp>(__e)}; }
template<typename _Tp, typename _Up>
auto
operator()(_Tp&& __e, _Up&& __f) const
{ return iota_view{std::forward<_Tp>(__e), std::forward<_Tp>(__f)}; }
};
inline constexpr _Iota iota{};
} // namespace views
} // namespace ranges
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment