From 7223c0428b1ef2a755a2c547a50d61e8de941a28 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 21 Jul 2020 21:38:10 -0700 Subject: [PATCH 1/5] Implement ranges::ssize ...per the proposed resolution of LWG-3403, which I just wrote and submitted to the LWG issues list (https://github.com/cplusplus/LWG/pull/328). --- stl/inc/xutility | 45 +++++++++++++++---- stl/inc/yvals_core.h | 1 + .../P0896R4_ranges_range_machinery/test.cpp | 14 +++++- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index f80ed07fa8..da38ffa851 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -755,6 +755,10 @@ concept weakly_incrementable = default_initializable<_Ty> && movable<_Ty> && req template using _Make_unsigned_like_t = make_unsigned_t<_Ty>; +// ALIAS TEMPLATE _Make_signed_like_t +template +using _Make_signed_like_t = make_signed_t<_Ty>; // Per the proposed resolution of LWG-3403 + // CONCEPT incrementable template concept incrementable = regular<_Ty> && weakly_incrementable<_Ty> && requires(_Ty __t) { @@ -3121,7 +3125,7 @@ namespace ranges { ~_Not_quite_object() = default; }; - // CLASS ranges::_Advance_fn + // VARIABLE ranges::advance class _Advance_fn : private _Not_quite_object { public: using _Not_quite_object::_Not_quite_object; @@ -3211,10 +3215,9 @@ namespace ranges { } }; - // VARIABLE ranges::advance inline constexpr _Advance_fn advance{_Not_quite_object::_Construct_tag{}}; - // CLASS ranges::_Distance_fn + // VARIABLE ranges::distance class _Distance_fn : private _Not_quite_object { public: using _Not_quite_object::_Not_quite_object; @@ -3246,10 +3249,38 @@ namespace ranges { } }; - // VARIABLE ranges::distance inline constexpr _Distance_fn distance{_Not_quite_object::_Construct_tag{}}; - // CLASS ranges::_Next_fn + // VARIABLE ranges::ssize + class _Ssize_fn { // Per the proposed resolution of LWG-3403 + public: + // clang-format off + template + _NODISCARD constexpr auto operator()(_Rng&& _Range) const requires requires { _RANGES size(_Range); } { + using _SSSsssigned = _Make_signed_like_t; + using _Ty = typename _Parsel_type>::template _Apply<_SSSsssigned>; + return static_cast<_Ty>(_RANGES size(_Range)); + } + // clang-format on + private: + template + struct _Parsel_type { + template + using _Apply = common_type_t; + }; + + template <> + struct _Parsel_type { + template + using _Apply = _Ty; + }; + }; + + inline namespace _Cpos { + inline constexpr _Ssize_fn ssize; + } + + // VARIABLE ranges::next class _Next_fn : private _Not_quite_object { public: using _Not_quite_object::_Not_quite_object; @@ -3279,10 +3310,9 @@ namespace ranges { } }; - // VARIABLE ranges::next inline constexpr _Next_fn next{_Not_quite_object::_Construct_tag{}}; - // CLASS ranges::_Prev_fn + // VARIABLE ranges::prev class _Prev_fn : private _Not_quite_object { public: using _Not_quite_object::_Not_quite_object; @@ -3308,7 +3338,6 @@ namespace ranges { } }; - // VARIABLE ranges::prev inline constexpr _Prev_fn prev{_Not_quite_object::_Construct_tag{}}; // FUNCTION TEMPLATE _Find_last_iterator diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 61292ad030..36e2e531a9 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -204,6 +204,7 @@ // P1871R1 disable_sized_sentinel_for // P1872R0 span Should Have size_type, Not index_type // P1878R1 Constraining Readable Types +// P1907R2 ranges::ssize // P1956R1 has_single_bit(), bit_ceil(), bit_floor(), bit_width() // P1959R0 Removing weak_equality And strong_equality // P1964R2 Replacing boolean With boolean-testable diff --git a/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp index f74ed9425d..8b8e34e598 100644 --- a/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp @@ -61,6 +61,9 @@ concept CanEmpty = requires(R&& r) { ranges::empty(std::forward(r)); }; template concept CanSize = requires(R&& r) { ranges::size(std::forward(r)); }; +template +concept CanSSize = requires(R&& r) { ranges::ssize(std::forward(r)); }; + template concept CanSizeType = requires { typename ranges::range_size_t; }; @@ -116,6 +119,7 @@ STATIC_ASSERT(test_cpo(ranges::rend)); STATIC_ASSERT(test_cpo(ranges::crbegin)); STATIC_ASSERT(test_cpo(ranges::crend)); STATIC_ASSERT(test_cpo(ranges::size)); +STATIC_ASSERT(test_cpo(ranges::ssize)); STATIC_ASSERT(test_cpo(ranges::empty)); STATIC_ASSERT(test_cpo(ranges::data)); STATIC_ASSERT(test_cpo(ranges::cdata)); @@ -136,6 +140,7 @@ void test_cpo_ambiguity() { (void) crbegin(vri); (void) crend(vri); (void) size(vri); + (void) ssize(vri); (void) empty(vri); (void) data(vri); (void) cdata(vri); @@ -315,16 +320,20 @@ constexpr bool test_empty() { template constexpr bool test_size() { - // Validate ranges::size and ranges::sized_range + // Validate ranges::size, ranges::sized_range, and ranges::ssize STATIC_ASSERT(!is_valid || std::integral); STATIC_ASSERT(CanSize == is_valid); + STATIC_ASSERT(CanSSize == is_valid); STATIC_ASSERT(CanSizeType == is_valid); STATIC_ASSERT(ranges::sized_range == is_valid); if constexpr (is_valid) { STATIC_ASSERT(std::same_as())), Size>); STATIC_ASSERT(std::same_as, Size>); + using SS = std::common_type_t>; + STATIC_ASSERT(std::same_as())), SS>); + STATIC_ASSERT(CanEmpty); } @@ -1612,6 +1621,9 @@ namespace exhaustive_size_and_view_test { STATIC_ASSERT(ranges::sized_range == is_valid); if constexpr (is_valid) { STATIC_ASSERT(std::same_as())), Size>); + + using SS = std::common_type_t>; + STATIC_ASSERT(std::same_as())), SS>); } STATIC_ASSERT(ranges::view == IsView); From 44d2a94762b61d50dd5ecbd57d7e88da8b12e22a Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Wed, 22 Jul 2020 07:37:12 -0700 Subject: [PATCH 2/5] Stephan's review comments. --- stl/inc/xutility | 16 ++-------------- .../P0896R4_ranges_range_machinery/test.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index da38ffa851..66a021c570 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -3257,23 +3257,11 @@ namespace ranges { // clang-format off template _NODISCARD constexpr auto operator()(_Rng&& _Range) const requires requires { _RANGES size(_Range); } { - using _SSSsssigned = _Make_signed_like_t; - using _Ty = typename _Parsel_type>::template _Apply<_SSSsssigned>; + using _Sty = _Make_signed_like_t; + using _Ty = common_type_t, ptrdiff_t, _Sty>, _Sty>; return static_cast<_Ty>(_RANGES size(_Range)); } // clang-format on - private: - template - struct _Parsel_type { - template - using _Apply = common_type_t; - }; - - template <> - struct _Parsel_type { - template - using _Apply = _Ty; - }; }; inline namespace _Cpos { diff --git a/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp index 8b8e34e598..fae06afc25 100644 --- a/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp @@ -331,8 +331,8 @@ constexpr bool test_size() { STATIC_ASSERT(std::same_as())), Size>); STATIC_ASSERT(std::same_as, Size>); - using SS = std::common_type_t>; - STATIC_ASSERT(std::same_as())), SS>); + using SignedSize = std::common_type_t>; + STATIC_ASSERT(std::same_as())), SignedSize>); STATIC_ASSERT(CanEmpty); } @@ -1622,8 +1622,8 @@ namespace exhaustive_size_and_view_test { if constexpr (is_valid) { STATIC_ASSERT(std::same_as())), Size>); - using SS = std::common_type_t>; - STATIC_ASSERT(std::same_as())), SS>); + using SignedSize = std::common_type_t>; + STATIC_ASSERT(std::same_as())), SignedSize>); } STATIC_ASSERT(ranges::view == IsView); From d027cdc6c631f9016de86a8e47fe9df7acd06341 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Thu, 23 Jul 2020 09:08:12 -0700 Subject: [PATCH 3/5] Bool is not integer-like per as-yet-unnumbered LWG issue --- stl/inc/xutility | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 66a021c570..0ae5d5a858 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -741,15 +741,15 @@ concept indirectly_writable = requires(_It&& __i, _Ty&& __t) { const_cast&&>(*static_cast<_It&&>(__i)) = static_cast<_Ty&&>(__t); }; -// CONCEPT weakly_incrementable +// CONCEPT _Integer_like // clang-format off template -concept weakly_incrementable = default_initializable<_Ty> && movable<_Ty> && requires(_Ty __i) { - typename iter_difference_t<_Ty>; - requires signed_integral>; - { ++__i } -> same_as<_Ty&>; - __i++; -}; +concept _Integer_like = _Is_nonbool_integral<_Ty>; // Per LWG issue submitted but unnumbered as of 20200723. + +// CONCEPT _Signed_integer_like +template +concept _Signed_integer_like = _Integer_like<_Ty> && _Ty(-1) < _Ty(0); +// clang-format on // ALIAS TEMPLATE _Make_unsigned_like_t template @@ -759,6 +759,16 @@ using _Make_unsigned_like_t = make_unsigned_t<_Ty>; template using _Make_signed_like_t = make_signed_t<_Ty>; // Per the proposed resolution of LWG-3403 +// CONCEPT weakly_incrementable +// clang-format off +template +concept weakly_incrementable = default_initializable<_Ty> && movable<_Ty> && requires(_Ty __i) { + typename iter_difference_t<_Ty>; + requires _Signed_integer_like>; + { ++__i } -> same_as<_Ty&>; + __i++; +}; + // CONCEPT incrementable template concept incrementable = regular<_Ty> && weakly_incrementable<_Ty> && requires(_Ty __t) { @@ -2835,12 +2845,12 @@ namespace ranges { // clang-format off template concept _Has_member = !disable_sized_range<_UnCV> && requires(_Ty __t) { - { _Fake_decay_copy(__t.size()) } -> integral; + { _Fake_decay_copy(__t.size()) } -> _Integer_like; }; template concept _Has_ADL = _Has_class_or_enum_type<_Ty> && !disable_sized_range<_UnCV> && requires(_Ty __t) { - { _Fake_decay_copy(size(__t)) } -> integral; + { _Fake_decay_copy(size(__t)) } -> _Integer_like; }; template From 527e11f2620b828dc27a984ddb76cf120df0b922 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Thu, 23 Jul 2020 17:48:52 -0700 Subject: [PATCH 4/5] More STL review comments --- stl/inc/concepts | 2 +- stl/inc/type_traits | 2 +- stl/inc/xutility | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/concepts b/stl/inc/concepts index 2cc8f904ba..4da6a23f49 100644 --- a/stl/inc/concepts +++ b/stl/inc/concepts @@ -79,7 +79,7 @@ concept integral = is_integral_v<_Ty>; // CONCEPT signed_integral template -concept signed_integral = integral<_Ty> && _Ty(-1) < _Ty(0); +concept signed_integral = integral<_Ty> && static_cast<_Ty>(-1) < static_cast<_Ty>(0); // CONCEPT unsigned_integral template diff --git a/stl/inc/type_traits b/stl/inc/type_traits index e17f1b7381..48ec61ed30 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -905,7 +905,7 @@ template > struct _Sign_base { // determine whether integral type _Ty is signed or unsigned using _Uty = remove_cv_t<_Ty>; - static constexpr bool _Signed = _Uty(-1) < _Uty(0); + static constexpr bool _Signed = static_cast<_Uty>(-1) < static_cast<_Uty>(0); static constexpr bool _Unsigned = !_Signed; }; diff --git a/stl/inc/xutility b/stl/inc/xutility index 0ae5d5a858..638393f7bd 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -744,11 +744,11 @@ concept indirectly_writable = requires(_It&& __i, _Ty&& __t) { // CONCEPT _Integer_like // clang-format off template -concept _Integer_like = _Is_nonbool_integral<_Ty>; // Per LWG issue submitted but unnumbered as of 20200723. +concept _Integer_like = _Is_nonbool_integral<_Ty>; // Per LWG issue submitted but unnumbered as of 2020-07-23. // CONCEPT _Signed_integer_like template -concept _Signed_integer_like = _Integer_like<_Ty> && _Ty(-1) < _Ty(0); +concept _Signed_integer_like = _Integer_like<_Ty> && static_cast<_Ty>(-1) < static_cast<_Ty>(0); // clang-format on // ALIAS TEMPLATE _Make_unsigned_like_t From 310e13c802a92a7a6969b811157d19395d6ab12f Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Sun, 26 Jul 2020 07:49:12 -0700 Subject: [PATCH 5/5] LWG-3467 now has a number. --- stl/inc/xutility | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 638393f7bd..71dec8d8fa 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -744,7 +744,7 @@ concept indirectly_writable = requires(_It&& __i, _Ty&& __t) { // CONCEPT _Integer_like // clang-format off template -concept _Integer_like = _Is_nonbool_integral<_Ty>; // Per LWG issue submitted but unnumbered as of 2020-07-23. +concept _Integer_like = _Is_nonbool_integral<_Ty>; // per the proposed resolution of LWG-3467 // CONCEPT _Signed_integer_like template @@ -757,7 +757,7 @@ using _Make_unsigned_like_t = make_unsigned_t<_Ty>; // ALIAS TEMPLATE _Make_signed_like_t template -using _Make_signed_like_t = make_signed_t<_Ty>; // Per the proposed resolution of LWG-3403 +using _Make_signed_like_t = make_signed_t<_Ty>; // per the proposed resolution of LWG-3403 // CONCEPT weakly_incrementable // clang-format off