diff --git a/stl/inc/__msvc_iter_core.hpp b/stl/inc/__msvc_iter_core.hpp index e0d383213a..c88b5a6a1c 100644 --- a/stl/inc/__msvc_iter_core.hpp +++ b/stl/inc/__msvc_iter_core.hpp @@ -50,6 +50,12 @@ _EXPORT_STD struct random_access_iterator_tag : bidirectional_iterator_tag {}; #ifdef __cpp_lib_concepts _EXPORT_STD struct contiguous_iterator_tag : random_access_iterator_tag {}; +template +using _With_reference = _Ty&; + +template +concept _Can_reference = requires { typename _With_reference<_Ty>; }; + template concept _Dereferenceable = requires(_Ty& __t) { { *__t } -> _Can_reference; diff --git a/stl/inc/ranges b/stl/inc/ranges index c19ab8e0e0..280c879dc9 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -105,9 +105,6 @@ namespace ranges { template concept _Has_arrow = input_iterator<_It> && (is_pointer_v<_It> || _Has_member_arrow<_It&>); - template - using _Maybe_const = conditional_t<_IsConst, const _Ty, _Ty>; - template using _Maybe_wrapped = conditional_t<_IsWrapped, _Ty, _Unwrapped_t<_Ty>>; @@ -8213,9 +8210,13 @@ namespace ranges { private: friend zip_view; +#ifdef __clang__ // TRANSITION, LLVM-61763 + public: +#else // ^^^ workaround / no workaround vvv template requires _Zip_transform_constraints<_Func, _OtherViews...> friend class zip_transform_view; +#endif // ^^^ no workaround ^^^ using _My_tuple = tuple>...>; @@ -9047,7 +9048,7 @@ namespace ranges { private: friend adjacent_view; -#ifdef __clang__ // TRANSITION, Clang 17 +#ifdef __clang__ // TRANSITION, LLVM-61763 public: #else // ^^^ workaround / no workaround vvv template diff --git a/stl/inc/type_traits b/stl/inc/type_traits index 2339de93f1..42842466e9 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -2513,6 +2513,9 @@ _NODISCARD constexpr _To _Bit_cast(const _From& _Val) noexcept { return __builtin_bit_cast(_To, _Val); } +template +using _Maybe_const = conditional_t<_IsConst, const _Ty, _Ty>; + #if _HAS_TR1_NAMESPACE _STL_DISABLE_DEPRECATED_WARNING namespace _DEPRECATE_TR1_NAMESPACE tr1 { diff --git a/stl/inc/utility b/stl/inc/utility index cadbcb51e2..d3c1f405ee 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -898,20 +898,6 @@ _NODISCARD constexpr bool in_range(const _Ty _Value) noexcept { return true; } - -#ifdef __cpp_lib_concepts -template -using _With_reference = _Ty&; - -template -concept _Can_reference = requires { typename _With_reference<_Ty>; }; -#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv -template -inline constexpr bool _Can_reference = false; - -template -inline constexpr bool _Can_reference<_Ty, void_t<_Ty&>> = true; -#endif // ^^^ !defined(__cpp_lib_concepts) ^^^ #endif // _HAS_CXX20 #if _HAS_CXX23 @@ -927,29 +913,14 @@ _EXPORT_STD [[noreturn]] __forceinline void unreachable() noexcept /* strengthen #endif // defined(_DEBUG) } +template >, remove_reference_t<_Uty>>> +using _Forward_like_t = conditional_t, _Tmp&&, _Tmp&>; + _EXPORT_STD template -_NODISCARD _MSVC_INTRINSIC constexpr auto&& forward_like(_Uty&& _Ux) noexcept { - static_assert(_Can_reference<_Ty>, "std::forward_like's first template argument must be a referenceable type."); - - using _UnrefT = remove_reference_t<_Ty>; - using _UnrefU = remove_reference_t<_Uty>; - if constexpr (is_const_v<_UnrefT>) { - if constexpr (is_lvalue_reference_v<_Ty>) { - return static_cast(_Ux); - } else { - return static_cast(_Ux); - } - } else { - if constexpr (is_lvalue_reference_v<_Ty>) { - return static_cast<_UnrefU&>(_Ux); - } else { - return static_cast<_UnrefU&&>(_Ux); - } - } +_NODISCARD _MSVC_INTRINSIC constexpr _Forward_like_t<_Ty, _Uty> forward_like(_Uty&& _Ux) noexcept { + return static_cast<_Forward_like_t<_Ty, _Uty>>(_Ux); } - -template -using _Forward_like_t = decltype(_STD forward_like<_Ty>(_STD declval<_Uty&>())); #endif // _HAS_CXX23 #if _HAS_TR1_NAMESPACE diff --git a/tests/std/tests/P2321R2_views_zip_transform/test.cpp b/tests/std/tests/P2321R2_views_zip_transform/test.cpp index c4667da11d..894d883763 100644 --- a/tests/std/tests/P2321R2_views_zip_transform/test.cpp +++ b/tests/std/tests/P2321R2_views_zip_transform/test.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -18,9 +19,12 @@ using namespace std; template using AllView = views::all_t; +template +using maybe_const = conditional_t; + template -using TransformResultType = invoke_result_t&, - ranges::range_reference_t>...>; +using TransformResultType = invoke_result_t&, + ranges::range_reference_t>...>; template constexpr auto& maybe_as_const(T& value) { @@ -50,8 +54,8 @@ constexpr bool validate_iterators_sentinels( constexpr bool is_const = same_as>; using InnerView = ranges::zip_view...>; - using BaseType = ranges::_Maybe_const; - using ZipIteratorTupleType = tuple>>...>; + using BaseType = maybe_const; + using ZipIteratorTupleType = tuple>>...>; // Validate iterator type aliases { @@ -66,8 +70,8 @@ constexpr bool validate_iterators_sentinels( STATIC_ASSERT(same_as); } else { constexpr auto check_iterator_tags_closure = []() { - return (derived_from>>::iterator_category, + return (derived_from>>::iterator_category, TagType> && ...); }; @@ -125,10 +129,9 @@ constexpr bool validate_iterators_sentinels( // // Notably, parent_t is a pointer and inner_.current_ is a tuple, and operator->() on a pointer and // std::get(std::tuple<...>) are both noexcept. We thus simplify the noexcept check as follows: - STATIC_ASSERT( - noexcept(*itr) - == noexcept(invoke(*declval&>(), - *declval>>&>()...))); + STATIC_ASSERT(noexcept(*itr) + == noexcept(invoke(*declval&>(), + *declval>>&>()...))); } STATIC_ASSERT(noexcept(++itr) == noexcept(++declval&>())); @@ -232,7 +235,7 @@ constexpr bool validate_iterators_sentinels( // Validate sentinel operator overloads { const auto validate_iterator_sentinel_equality_closure = [&]() { - using comparison_iterator_t = ranges::iterator_t>; + using comparison_iterator_t = ranges::iterator_t>; using comparison_sentinel_t = ranges::sentinel_t; if constexpr (sentinel_for) { @@ -254,11 +257,11 @@ constexpr bool validate_iterators_sentinels( { const auto validate_iterator_sentinel_difference_closure = [&]() { - using comparison_iterator_t = ranges::iterator_t>; + using comparison_iterator_t = ranges::iterator_t>; using comparison_sentinel_t = ranges::sentinel_t; if constexpr (sized_sentinel_for) { - using difference_type = ranges::range_difference_t>; + using difference_type = ranges::range_difference_t>; const auto comparison_itr = maybe_as_const(relevant_range).begin(); @@ -515,9 +518,9 @@ constexpr bool test_one(TransformType_&& transformer, const TransformedElementsC // Validate view_interface::front() { const auto validate_front_closure = [&]() { - STATIC_ASSERT(CanMemberFront> - == ranges::forward_range>); - if constexpr (CanMemberFront>) { + STATIC_ASSERT(CanMemberFront> + == ranges::forward_range>); + if constexpr (CanMemberFront>) { using transform_result_t = TransformResultType; same_as auto first_result = maybe_as_const(zipped_transformed_range).front(); @@ -533,10 +536,10 @@ constexpr bool test_one(TransformType_&& transformer, const TransformedElementsC // Validate view_interface::back() { const auto validate_back_closure = [&]() { - STATIC_ASSERT(CanMemberBack> - == (ranges::bidirectional_range> - && ranges::common_range>) ); - if constexpr (CanMemberBack>) { + STATIC_ASSERT(CanMemberBack> + == (ranges::bidirectional_range> + && ranges::common_range>) ); + if constexpr (CanMemberBack>) { using transform_result_t = TransformResultType; same_as auto last_result = maybe_as_const(zipped_transformed_range).back(); @@ -552,9 +555,9 @@ constexpr bool test_one(TransformType_&& transformer, const TransformedElementsC // Validate view_interface::operator[] { const auto validate_random_access_closure = [&]() { - STATIC_ASSERT(CanIndex> - == ranges::random_access_range>); - if constexpr (CanIndex>) { + STATIC_ASSERT(CanIndex> + == ranges::random_access_range>); + if constexpr (CanIndex>) { using transform_result_t = TransformResultType; same_as auto first_result = maybe_as_const(zipped_transformed_range)[0];