From a7f8ca679bf3d9283bc6bbfbffef689ff8edf090 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Sat, 7 Jan 2023 23:17:02 -0800 Subject: [PATCH 1/6] ```: simplify `zip_view::_Size_closure`` ... by making it a `static constexpr` data member instead of a function --- stl/inc/ranges | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index db45abf8e13..13c53ff65bb 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -7455,6 +7455,11 @@ namespace ranges { } } + static constexpr auto _Size_closure = [](auto... _Sizes) _STATIC_CALL_OPERATOR noexcept { + using _Common_unsigned_type = _Make_unsigned_like_t>; + return (_RANGES min)({static_cast<_Common_unsigned_type>(_Sizes)...}); + }; + public: zip_view() noexcept((is_nothrow_default_constructible_v<_ViewTypes> && ...)) = default; @@ -7501,25 +7506,17 @@ namespace ranges { } _NODISCARD constexpr auto size() noexcept( - noexcept(_STD apply(_Size_closure(), _Tuple_transform(_RANGES size, _Views)))) // strengthened + noexcept(_STD apply(_Size_closure, _Tuple_transform(_RANGES size, _Views)))) // strengthened requires (sized_range<_ViewTypes> && ...) { - return _STD apply(_Size_closure(), _Tuple_transform(_RANGES size, _Views)); + return _STD apply(_Size_closure, _Tuple_transform(_RANGES size, _Views)); } _NODISCARD constexpr auto size() const - noexcept(noexcept(_STD apply(_Size_closure(), _Tuple_transform(_RANGES size, _Views)))) // strengthened + noexcept(noexcept(_STD apply(_Size_closure, _Tuple_transform(_RANGES size, _Views)))) // strengthened requires (sized_range && ...) { - return _STD apply(_Size_closure(), _Tuple_transform(_RANGES size, _Views)); - } - - private: - _NODISCARD static constexpr auto _Size_closure() noexcept { - return [](auto... _Sizes) _STATIC_CALL_OPERATOR noexcept { - using _Common_unsigned_type = _Make_unsigned_like_t>; - return (_RANGES min)({static_cast<_Common_unsigned_type>(_Sizes)...}); - }; + return _STD apply(_Size_closure, _Tuple_transform(_RANGES size, _Views)); } }; From f39ca32249b5193d824ad901af7397e0bad82598 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Wed, 11 Jan 2023 17:56:51 -0800 Subject: [PATCH 2/6] Use conventional LLVM issue linking style --- tests/std/tests/P0323R12_expected/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P0323R12_expected/test.cpp b/tests/std/tests/P0323R12_expected/test.cpp index 1c97c0092c3..82a8d09d0ed 100644 --- a/tests/std/tests/P0323R12_expected/test.cpp +++ b/tests/std/tests/P0323R12_expected/test.cpp @@ -2232,8 +2232,8 @@ void test_reinit_regression() { } } -// Defend against regression of llvm-project#59854, in which clang is confused -// by the explicit `noexcept` on `expected`'s destructors. +// Defend against regression of LLVM-59854, in which clang is confused by the +// explicit `noexcept` on `expected`'s destructors. struct Data { vector vec_; constexpr Data(initializer_list il) : vec_(il) {} From 734be4c36bdaa40fa8377ec2972164420d94c47f Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 23 Jan 2023 12:16:36 -0800 Subject: [PATCH 3/6] Simplify `_Tuple_like` metaprogramming Implements `_Tuple_like_impl` as a variable template with four partial specializations instead of as a disjunction of four other variable template specializations. Consequently, each evaluation of `_Tuple_like` causes the compiler to memoize one constexpr variable instead of five. --- stl/inc/__msvc_iter_core.hpp | 3 +++ stl/inc/span | 6 ++++++ stl/inc/utility | 20 +++++++++++--------- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/stl/inc/__msvc_iter_core.hpp b/stl/inc/__msvc_iter_core.hpp index 6107a8700aa..88007373b96 100644 --- a/stl/inc/__msvc_iter_core.hpp +++ b/stl/inc/__msvc_iter_core.hpp @@ -456,6 +456,9 @@ _EXPORT_STD using ranges::get; template constexpr bool _Is_subrange_v> = true; +template +constexpr bool _Tuple_like_impl> = true; + template struct tuple_size> : integral_constant {}; diff --git a/stl/inc/span b/stl/inc/span index 018bc98cc98..d30d805d105 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -235,6 +235,12 @@ constexpr bool _Is_span_v = false; template constexpr bool _Is_span_v> = true; +template +constexpr bool _Is_std_array_v = false; + +template +constexpr bool _Is_std_array_v> = true; + // clang-format off template concept _Span_compatible_iterator = contiguous_iterator<_It> diff --git a/stl/inc/utility b/stl/inc/utility index f86e318e398..2281bf7c019 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -200,19 +200,21 @@ _NODISCARD constexpr const _Ty&& get(const array<_Ty, _Size>&& _Arr) noexcept; template concept _Different_from = !same_as, remove_cvref_t<_Ty2>>; -template -constexpr bool _Is_std_array_v = false; - -template -constexpr bool _Is_std_array_v> = true; - template constexpr bool _Is_subrange_v = false; #if _HAS_CXX23 -template -constexpr bool _Tuple_like_impl = - _Is_specialization_v<_Ty, tuple> || _Is_specialization_v<_Ty, pair> || _Is_std_array_v<_Ty> || _Is_subrange_v<_Ty>; +template +constexpr bool _Tuple_like_impl = false; + +template +constexpr bool _Tuple_like_impl> = true; + +template +constexpr bool _Tuple_like_impl> = true; + +template +constexpr bool _Tuple_like_impl> = true; template concept _Tuple_like = _Tuple_like_impl>; From 0ec9fee7e7881b93b0b932adccedb06afb271c7e Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 20 Aug 2024 11:50:44 -0700 Subject: [PATCH 4/6] Don't return a decayed *boolean-testable* ... since the exposition-only concept doesn't allow for construction of an object of decayed type from a model of *boolean-testable*. Note that the changes in `erase_if(forward_list, pred)` and `erase_if(list, pred)` are the proposed resolution of LWG-4135, which I feel is a no-brainer and can be implemented without comments. I audited for other occurrences after noticing we do the same thing in `forward_list::remove` and `list::remove`. The fold expressions in `` are a weird case: they are only problematic when the pack has one element. For zero or more than one elements, the fold expression has type `bool`, but with exactly one element it's a *boolean-testable* that the lambda implicitly decays on return. I think it's a bit more elegant to fix these by adding `|| false` to the fold expressions to make them binary than to explicitly specify the return type of the lambda. --- stl/inc/forward_list | 4 ++-- stl/inc/list | 4 ++-- stl/inc/ranges | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/stl/inc/forward_list b/stl/inc/forward_list index afcdbf99254..ead270e4c99 100644 --- a/stl/inc/forward_list +++ b/stl/inc/forward_list @@ -1209,7 +1209,7 @@ public: }; auto remove(const _Ty& _Val) { // erase each element matching _Val - return remove_if([&](const _Ty& _Other) { return _Other == _Val; }); + return remove_if([&](const _Ty& _Other) -> bool { return _Other == _Val; }); } template @@ -1614,7 +1614,7 @@ _NODISCARD bool operator>=(const forward_list<_Ty, _Alloc>& _Left, const forward #if _HAS_CXX20 _EXPORT_STD template forward_list<_Ty, _Alloc>::size_type erase(forward_list<_Ty, _Alloc>& _Cont, const _Uty& _Val) { - return _Cont.remove_if([&](_Ty& _Elem) { return _Elem == _Val; }); + return _Cont.remove_if([&](_Ty& _Elem) -> bool { return _Elem == _Val; }); } _EXPORT_STD template diff --git a/stl/inc/list b/stl/inc/list index 84160362f46..3d427f80e6e 100644 --- a/stl/inc/list +++ b/stl/inc/list @@ -1663,7 +1663,7 @@ public: }; auto remove(const _Ty& _Val) { // erase each element matching _Val - return remove_if([&](const _Ty& _Other) { return _Other == _Val; }); + return remove_if([&](const _Ty& _Other) -> bool { return _Other == _Val; }); } template @@ -1916,7 +1916,7 @@ _NODISCARD bool operator>=(const list<_Ty, _Alloc>& _Left, const list<_Ty, _Allo #if _HAS_CXX20 _EXPORT_STD template list<_Ty, _Alloc>::size_type erase(list<_Ty, _Alloc>& _Cont, const _Uty& _Val) { - return _Cont.remove_if([&](_Ty& _Elem) { return _Elem == _Val; }); + return _Cont.remove_if([&](_Ty& _Elem) -> bool { return _Elem == _Val; }); } _EXPORT_STD template diff --git a/stl/inc/ranges b/stl/inc/ranges index 13c53ff65bb..31eb543b493 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -7134,7 +7134,7 @@ namespace ranges { const auto _Evaluate_equality_closure = [&_Lhs_tuple, &_Rhs_tuple](index_sequence<_Indices...>) noexcept( (noexcept(_STD declval() == _STD declval())&&...)) { - return ((_STD get<_Indices>(_Lhs_tuple) == _STD get<_Indices>(_Rhs_tuple)) || ...); + return ((_STD get<_Indices>(_Lhs_tuple) == _STD get<_Indices>(_Rhs_tuple)) || ... || false); }; return _Evaluate_equality_closure(index_sequence_for<_LHSTupleTypes...>{}); @@ -9141,7 +9141,7 @@ namespace ranges { requires ((!_Simple_view<_First> || ... || !_Simple_view<_Rest>) && _Cartesian_product_is_common<_First>) { const bool _Is_empty = [&](index_sequence<_Indices...>) { - return (_RANGES empty(_STD get<_Indices + 1>(_Bases)) || ...); + return (_RANGES empty(_STD get<_Indices + 1>(_Bases)) || ... || false); }(make_index_sequence{}); const auto _Make_iter_tuple = [&](index_sequence<_Indices...>) { @@ -9154,7 +9154,7 @@ namespace ranges { requires _Cartesian_product_is_common { const bool _Is_empty = [&](index_sequence<_Indices...>) { - return (_RANGES empty(_STD get<_Indices + 1>(_Bases)) || ...); + return (_RANGES empty(_STD get<_Indices + 1>(_Bases)) || ... || false); }(make_index_sequence{}); const auto _Make_iter_tuple = [&](index_sequence<_Indices...>) { From 8d4e319bdb3ad8cf39ec9435c4bf8c0c509fe41f Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 20 Aug 2024 11:53:09 -0700 Subject: [PATCH 5/6] Don't `return` in `cartesian_product_view::_Iterator::iter_swap` We _can_ `return` an expression with `void` type in a function with return type `void`, but we typically don't do so when the types are concrete. --- stl/inc/ranges | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 31eb543b493..62b8d6a1243 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -9091,9 +9091,8 @@ namespace ranges { requires (indirectly_swappable>> && ... && indirectly_swappable>>) { - return [&](index_sequence<_Indices...>) { - return (_RANGES iter_swap(_STD get<_Indices>(_Left._Current), _STD get<_Indices>(_Right._Current)), - ...); + [&](index_sequence<_Indices...>) { + (_RANGES iter_swap(_STD get<_Indices>(_Left._Current), _STD get<_Indices>(_Right._Current)), ...); }(make_index_sequence<1 + sizeof...(_Rest)>{}); } }; From cd2ac04978a4ae2512003416bbafe54302af7561 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 20 Aug 2024 13:07:25 -0700 Subject: [PATCH 6/6] `_Tuple_like_impl` is `_HAS_CXX23`-only --- stl/inc/__msvc_iter_core.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stl/inc/__msvc_iter_core.hpp b/stl/inc/__msvc_iter_core.hpp index 88007373b96..cc52fada0df 100644 --- a/stl/inc/__msvc_iter_core.hpp +++ b/stl/inc/__msvc_iter_core.hpp @@ -456,8 +456,10 @@ _EXPORT_STD using ranges::get; template constexpr bool _Is_subrange_v> = true; +#if _HAS_CXX23 template constexpr bool _Tuple_like_impl> = true; +#endif // _HAS_CXX23 template struct tuple_size> : integral_constant {};