From 6733d164d038fc2c30e7380b5f14587c61c22b3e Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Sat, 7 Sep 2019 07:05:33 -0700 Subject: [PATCH] Ranges machinery * Implements a selection of support machinery in `std::ranges` and adds the `` header. Primarily consists of the range access customization point objects: * `ranges::begin` * `ranges::end` * `ranges::cbegin` * `ranges::cend` * `ranges::rbegin` * `ranges::rend` * `ranges::crbegin` * `ranges::crend` * `ranges::size` * `ranges::empty` * `ranges::data` * `ranges::cdata` and range concepts: * `ranges::range` * `ranges::output_range` * `ranges::input_range` * `ranges::forward_range` * `ranges::bidirectional_range` * `ranges::random_access_range` * `ranges::contiguous_range` * `ranges::sized_range` * `ranges::view` * `ranges::common_range` and the associated type aliases: * `ranges::iterator_t` * `ranges::sentinel_t` * `ranges::range_value_t` * `ranges::range_reference_t` * `ranges::range_difference_t` * `ranges::range_rvalue_reference_t` * Adds `` - which is mostly empty since the support machinery is defined in `` so as to be visible to `` * Annotates [P0896R4](https://wg21.link/p0896r4) as partially implemented in the "`_HAS_CXX20` directly controls" section of ``. * Touches ``, ``, and `` to add partial specializations of `ranges::enable_view` for `match_results` and `(unordered_)?multi?set` as mandated by the WD to override the heuristic. * Partially implements [P1474R1 "Helpful pointers for `ContiguousIterator`"](https://wg21.link/p1474r1): * Push `pointer_traits` from `` and `to_address` from `` up into `` * Add `to_address` expression requirement to `contiguous_iterator` concept, and update `P0896R4_ranges_iterator_machinery` appropriately * Implement the changes to `ranges::data` (but not `view_interface` since it isn't yet implemented) * Drive-by: * Simplify the definition of `pointer_traits::_Reftype` by eschewing `add_lvalue_reference_t`. * Strengthen `reverse_iterator`'s constructors and `make_reverse_iterator` so `ranges::rbegin` and `ranges::rend` can be `noexcept` in more cases * Since we're using `_Rng` as the template parameter name for models of `std::ranges::range`, rename a local variable `_Rng` to `_Generator` in `` --- stl/CMakeLists.txt | 1 + stl/inc/__msvc_all_public_headers.hpp | 1 + stl/inc/concepts | 12 +- stl/inc/hash_map | 4 +- stl/inc/hash_set | 15 +- stl/inc/memory | 26 - stl/inc/random | 6 +- stl/inc/regex | 7 + stl/inc/set | 10 + stl/inc/unordered_set | 10 + stl/inc/xmemory | 84 -- stl/inc/xtr1common | 13 +- stl/inc/xutility | 1038 ++++++++++++++++++++++--- stl/inc/yvals_core.h | 16 +- 14 files changed, 998 insertions(+), 245 deletions(-) diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index cddab6e8f81..c409cea89b1 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -164,6 +164,7 @@ set(HEADERS ${CMAKE_CURRENT_LIST_DIR}/inc/ostream ${CMAKE_CURRENT_LIST_DIR}/inc/queue ${CMAKE_CURRENT_LIST_DIR}/inc/random + ${CMAKE_CURRENT_LIST_DIR}/inc/ranges ${CMAKE_CURRENT_LIST_DIR}/inc/ratio ${CMAKE_CURRENT_LIST_DIR}/inc/regex ${CMAKE_CURRENT_LIST_DIR}/inc/scoped_allocator diff --git a/stl/inc/__msvc_all_public_headers.hpp b/stl/inc/__msvc_all_public_headers.hpp index eb29c0733d6..85862ca6788 100644 --- a/stl/inc/__msvc_all_public_headers.hpp +++ b/stl/inc/__msvc_all_public_headers.hpp @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include diff --git a/stl/inc/concepts b/stl/inc/concepts index 71e34b7ccbd..f01d2b535d6 100644 --- a/stl/inc/concepts +++ b/stl/inc/concepts @@ -121,6 +121,10 @@ concept default_initializable = constructible_from<_Ty> template concept move_constructible = constructible_from<_Ty, _Ty> && convertible_to<_Ty, _Ty>; +// CONCEPT _Has_class_or_enum_type +template +concept _Has_class_or_enum_type = __is_class(remove_reference_t<_Ty>) || __is_enum(remove_reference_t<_Ty>); + // CUSTOMIZATION POINT OBJECT ranges::swap namespace ranges { namespace _Swap { @@ -131,12 +135,8 @@ namespace ranges { template void swap(_Ty&, _Ty&) = delete; - template - inline constexpr bool _Is_class_or_enum = __is_class(_Ty) || __is_enum(_Ty); - template - concept _Use_ADL_swap = - (_Is_class_or_enum> || _Is_class_or_enum>) + concept _Use_ADL_swap = (_Has_class_or_enum_type<_Ty1> || _Has_class_or_enum_type<_Ty2>) && requires(_Ty1&& __t, _Ty2&& __u) { swap(static_cast<_Ty1&&>(__t), static_cast<_Ty2&&>(__u)); }; @@ -364,7 +364,7 @@ _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) #else // ^^^ supported / not supported vvv -#pragma message("The contents of are only available with C++20 or later.") +#pragma message("The contents of are only available with C++20 concepts support.") #endif // __cpp_lib_concepts #endif // _STL_COMPILER_PREPROCESSOR #endif // _CONCEPTS_ diff --git a/stl/inc/hash_map b/stl/inc/hash_map index 8d196b246e8..a90f093f50c 100644 --- a/stl/inc/hash_map +++ b/stl/inc/hash_map @@ -461,8 +461,8 @@ namespace stdext { } } // namespace stdext _STD_BEGIN -using stdext::hash_map; -using stdext::hash_multimap; +using _STDEXT hash_map; +using _STDEXT hash_multimap; _STD_END #pragma pop_macro("new") diff --git a/stl/inc/hash_set b/stl/inc/hash_set index 131da09d09d..491985741e1 100644 --- a/stl/inc/hash_set +++ b/stl/inc/hash_set @@ -379,9 +379,20 @@ namespace stdext { return !(_Left == _Right); } } // namespace stdext + _STD_BEGIN -using stdext::hash_multiset; -using stdext::hash_set; +using _STDEXT hash_multiset; +using _STDEXT hash_set; + +#ifdef __cpp_lib_concepts +namespace ranges { + template + inline constexpr bool enable_view<_STDEXT hash_set<_Kty, _Tr, _Alloc>> = false; + + template + inline constexpr bool enable_view<_STDEXT hash_multiset<_Kty, _Tr, _Alloc>> = false; +} // namespace ranges +#endif // __cpp_lib_concepts _STD_END #pragma pop_macro("new") diff --git a/stl/inc/memory b/stl/inc/memory index 23074d6c213..a400869a6c2 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -2173,32 +2173,6 @@ basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Out, c return _Out; } -#if _HAS_CXX20 -// FUNCTION TEMPLATE to_address -template -inline constexpr bool _Has_to_address_v = false; // determines whether _Ptr has pointer_traits<_Ptr>::to_address(p) - -template -inline constexpr bool - _Has_to_address_v<_Ptr, void_t::to_address(_STD declval()))>> = true; - -template -_NODISCARD constexpr _Ty* to_address(_Ty* const _Val) noexcept { - static_assert(!is_function_v<_Ty>, - "N4810 20.10.4 [pointer.conversion]/2: The program is ill-formed if T is a function type."); - return _Val; -} - -template -_NODISCARD auto to_address(const _Ptr& _Val) noexcept { - if constexpr (_Has_to_address_v<_Ptr>) { - return pointer_traits<_Ptr>::to_address(_Val); - } else { - return _STD to_address(_Val.operator->()); // plain pointer overload must come first - } -} -#endif // _HAS_CXX20 - // GARBAGE COLLECTION enum class pointer_safety { relaxed, preferred, strict }; diff --git a/stl/inc/random b/stl/inc/random index cca3bff0bc9..54be88e38a3 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -1851,7 +1851,7 @@ private: template result_type _Eval(_Engine& _Eng, _Ty _Min, _Ty _Max) const { // compute next value in range [_Min, _Max] - _Rng_from_urng<_Uty, _Engine> _Rng(_Eng); + _Rng_from_urng<_Uty, _Engine> _Generator(_Eng); const _Uty _Umin = _Adjust(_Uty(_Min)); const _Uty _Umax = _Adjust(_Uty(_Max)); @@ -1859,9 +1859,9 @@ private: _Uty _Uret; if (_Umax - _Umin == _Uty(-1)) { - _Uret = static_cast<_Uty>(_Rng._Get_all_bits()); + _Uret = static_cast<_Uty>(_Generator._Get_all_bits()); } else { - _Uret = static_cast<_Uty>(_Rng(static_cast<_Uty>(_Umax - _Umin + 1))); + _Uret = static_cast<_Uty>(_Generator(static_cast<_Uty>(_Umax - _Umin + 1))); } return static_cast<_Ty>(_Adjust(static_cast<_Uty>(_Uret + _Umin))); diff --git a/stl/inc/regex b/stl/inc/regex index f99c563881c..765b90af6d6 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -936,6 +936,13 @@ basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr, template >> class match_results; +#ifdef __cpp_lib_concepts +namespace ranges { + template + inline constexpr bool enable_view> = false; +} // namespace ranges +#endif // __cpp_lib_concepts + template _OutIt _Format_default(const match_results<_BidIt, _Alloc>& _Match, _OutIt _Out, _InIt _First, _InIt _Last, regex_constants::match_flag_type _Flags = regex_constants::format_default); diff --git a/stl/inc/set b/stl/inc/set index 792ece8f57f..9031bb02c85 100644 --- a/stl/inc/set +++ b/stl/inc/set @@ -322,6 +322,16 @@ namespace pmr { using multiset = _STD multiset<_Kty, _Pr, polymorphic_allocator<_Kty>>; } // namespace pmr #endif // _HAS_CXX17 + +#ifdef __cpp_lib_concepts +namespace ranges { + template + inline constexpr bool enable_view> = false; + + template + inline constexpr bool enable_view> = false; +} // namespace ranges +#endif // __cpp_lib_concepts _STD_END #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS diff --git a/stl/inc/unordered_set b/stl/inc/unordered_set index ff9705c39d2..27b05834708 100644 --- a/stl/inc/unordered_set +++ b/stl/inc/unordered_set @@ -593,6 +593,16 @@ namespace pmr { using unordered_multiset = _STD unordered_multiset<_Kty, _Hasher, _Keyeq, polymorphic_allocator<_Kty>>; } // namespace pmr #endif // _HAS_CXX17 + +#ifdef __cpp_lib_concepts +namespace ranges { + template + inline constexpr bool enable_view> = false; + + template + inline constexpr bool enable_view> = false; +} // namespace ranges +#endif // __cpp_lib_concepts _STD_END #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 71a03f8a711..0038184c553 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -221,90 +221,6 @@ _Ty* _Global_new(_Types&&... _Args) { // acts as "new" while disallowing user ov return static_cast<_Ty*>(_STD exchange(_Guard._Result, nullptr)); } -// STRUCT TEMPLATE _Get_first_parameter -template -struct _Get_first_parameter; - -template