diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -260,6 +260,8 @@ ------------------------------------------------- ----------------- ``__cpp_lib_math_constants`` ``201907L`` ------------------------------------------------- ----------------- + ``__cpp_lib_move_iterator_concept`` ``202207L`` + ------------------------------------------------- ----------------- ``__cpp_lib_polymorphic_allocator`` ``201902L`` ------------------------------------------------- ----------------- ``__cpp_lib_ranges`` ``202106L`` diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -37,6 +37,7 @@ Implemented Papers ------------------ +- P2520R0 - ``move_iterator`` should be a random access iterator - P1328R1 - ``constexpr type_info::operator==()`` diff --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv --- a/libcxx/docs/Status/Cxx2bPapers.csv +++ b/libcxx/docs/Status/Cxx2bPapers.csv @@ -84,7 +84,7 @@ "`P2508R1 `__","LWG","Exposing ``std::basic-format-string``","July 2022","|Complete|","15.0" "`P2513R4 `__","LWG","``char8_t`` Compatibility and Portability Fixes","July 2022","","" "`P2517R1 `__","LWG","Add a conditional ``noexcept`` specification to ``std::apply``","July 2022","","" -"`P2520R0 `__","LWG","``move_iterator`` should be a random access iterator","July 2022","","","|ranges|" +"`P2520R0 `__","LWG","``move_iterator`` should be a random access iterator","July 2022","|Complete|","17.0","|ranges|" "`P2540R1 `__","LWG","Empty Product for certain Views","July 2022","","","|ranges|" "`P2549R1 `__","LWG","``std::unexpected`` should have ``error()`` as member accessor","July 2022","|Complete|","16.0" "`P2553R1 `__","LWG","Make ``mdspan`` ``size_type`` controllable","July 2022","","" diff --git a/libcxx/include/__iterator/move_iterator.h b/libcxx/include/__iterator/move_iterator.h --- a/libcxx/include/__iterator/move_iterator.h +++ b/libcxx/include/__iterator/move_iterator.h @@ -67,10 +67,25 @@ : public __move_iter_category_base<_Iter> #endif { + #if _LIBCPP_STD_VER >= 20 +private: + _LIBCPP_HIDE_FROM_ABI + static constexpr auto __get_iter_concept() { + if constexpr (random_access_iterator<_Iter>) { + return random_access_iterator_tag{}; + } else if constexpr (bidirectional_iterator<_Iter>) { + return bidirectional_iterator_tag{}; + } else if constexpr (forward_iterator<_Iter>) { + return forward_iterator_tag{}; + } else { + return input_iterator_tag{}; + } + } +#endif // _LIBCPP_STD_VER >= 20 public: #if _LIBCPP_STD_VER >= 20 using iterator_type = _Iter; - using iterator_concept = input_iterator_tag; + using iterator_concept = decltype(__get_iter_concept()); // iterator_category is inherited and not always present using value_type = iter_value_t<_Iter>; using difference_type = iter_difference_t<_Iter>; diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -387,7 +387,7 @@ class move_iterator { public: using iterator_type = Iterator; - using iterator_concept = input_iterator_tag; // From C++20 + using iterator_concept = see below; // From C++20 using iterator_category = see below; // not always present starting from C++20 using value_type = iter_value_t; // Until C++20, iterator_traits::value_type using difference_type = iter_difference_t; // Until C++20, iterator_traits::difference_type; diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -122,6 +122,7 @@ __cpp_lib_math_constants 201907L __cpp_lib_math_special_functions 201603L __cpp_lib_memory_resource 201603L +__cpp_lib_move_iterator_concept 202207L __cpp_lib_move_only_function 202110L __cpp_lib_node_extract 201606L @@ -356,6 +357,7 @@ # endif # define __cpp_lib_list_remove_return_type 201806L # define __cpp_lib_math_constants 201907L +# define __cpp_lib_move_iterator_concept 202207L # define __cpp_lib_polymorphic_allocator 201902L # define __cpp_lib_ranges 202106L # define __cpp_lib_remove_cvref 201711L diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp @@ -56,8 +56,8 @@ static_assert( std::default_initializable); static_assert( std::copyable); - static_assert( std::input_iterator); - static_assert(!std::forward_iterator); + static_assert( std::forward_iterator); + static_assert(!std::bidirectional_iterator); static_assert( std::sentinel_for); static_assert(!std::sized_sentinel_for); static_assert(!std::indirectly_movable); @@ -73,8 +73,8 @@ static_assert( std::default_initializable); static_assert( std::copyable); - static_assert( std::input_iterator); - static_assert(!std::forward_iterator); + static_assert( std::bidirectional_iterator); + static_assert(!std::random_access_iterator); static_assert( std::sentinel_for); static_assert(!std::sized_sentinel_for); static_assert(!std::indirectly_movable); @@ -90,8 +90,8 @@ static_assert( std::default_initializable); static_assert( std::copyable); - static_assert( std::input_iterator); - static_assert(!std::forward_iterator); + static_assert( std::random_access_iterator); + static_assert(!std::contiguous_iterator); static_assert( std::sentinel_for); static_assert( std::sized_sentinel_for); static_assert(!std::indirectly_movable); @@ -107,8 +107,8 @@ static_assert( std::default_initializable); static_assert( std::copyable); - static_assert( std::input_iterator); - static_assert(!std::forward_iterator); + static_assert( std::random_access_iterator); + static_assert(!std::contiguous_iterator); static_assert( std::sentinel_for); static_assert( std::sized_sentinel_for); static_assert(!std::indirectly_movable); @@ -124,8 +124,8 @@ static_assert( std::default_initializable); static_assert( std::copyable); - static_assert( std::input_iterator); - static_assert(!std::forward_iterator); + static_assert( std::random_access_iterator); + static_assert(!std::contiguous_iterator); static_assert( std::sentinel_for); static_assert( std::sized_sentinel_for); static_assert(!std::indirectly_movable); diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/types.pass.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/types.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/types.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/types.pass.cpp @@ -16,7 +16,7 @@ // class move_iterator { // public: // using iterator_type = Iterator; -// using iterator_concept = input_iterator_tag; // From C++20 +// using iterator_concept = see below; // From C++20 // using iterator_category = see below; // not always present starting from C++20 // using value_type = iter_value_t; // Until C++20, iterator_traits::value_type // using difference_type = iter_difference_t; // Until C++20, iterator_traits::difference_type; @@ -99,7 +99,7 @@ #endif #if TEST_STD_VER > 17 - static_assert(std::is_same_v); + static_assert(std::is_same_v); #endif } @@ -142,11 +142,11 @@ #if TEST_STD_VER > 17 test>(); - static_assert(std::is_same_v>::iterator_concept, std::input_iterator_tag>); - static_assert(std::is_same_v>::iterator_concept, std::input_iterator_tag>); - static_assert(std::is_same_v>::iterator_concept, std::input_iterator_tag>); - static_assert(std::is_same_v>::iterator_concept, std::input_iterator_tag>); - static_assert(std::is_same_v::iterator_concept, std::input_iterator_tag>); + static_assert(std::is_same_v>::iterator_concept, std::forward_iterator_tag>); + static_assert(std::is_same_v>::iterator_concept, std::bidirectional_iterator_tag>); + static_assert(std::is_same_v>::iterator_concept, std::random_access_iterator_tag>); + static_assert(std::is_same_v>::iterator_concept, std::random_access_iterator_tag>); + static_assert(std::is_same_v::iterator_concept, std::random_access_iterator_tag>); #endif return 0; diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp @@ -20,6 +20,7 @@ 201811L [C++20] __cpp_lib_constexpr_iterator 201811L [C++20] __cpp_lib_make_reverse_iterator 201402L [C++14] + __cpp_lib_move_iterator_concept 202207L [C++20] __cpp_lib_nonmember_container_access 201411L [C++17] __cpp_lib_null_iterators 201304L [C++14] __cpp_lib_ranges 202106L [C++20] @@ -43,6 +44,10 @@ # error "__cpp_lib_make_reverse_iterator should not be defined before c++14" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++20" +# endif + # ifdef __cpp_lib_nonmember_container_access # error "__cpp_lib_nonmember_container_access should not be defined before c++17" # endif @@ -76,6 +81,10 @@ # error "__cpp_lib_make_reverse_iterator should have the value 201402L in c++14" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++20" +# endif + # ifdef __cpp_lib_nonmember_container_access # error "__cpp_lib_nonmember_container_access should not be defined before c++17" # endif @@ -115,6 +124,10 @@ # error "__cpp_lib_make_reverse_iterator should have the value 201402L in c++17" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++20" +# endif + # ifndef __cpp_lib_nonmember_container_access # error "__cpp_lib_nonmember_container_access should be defined in c++17" # endif @@ -160,6 +173,13 @@ # error "__cpp_lib_make_reverse_iterator should have the value 201402L in c++20" # endif +# ifndef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should be defined in c++20" +# endif +# if __cpp_lib_move_iterator_concept != 202207L +# error "__cpp_lib_move_iterator_concept should have the value 202207L in c++20" +# endif + # ifndef __cpp_lib_nonmember_container_access # error "__cpp_lib_nonmember_container_access should be defined in c++20" # endif @@ -211,6 +231,13 @@ # error "__cpp_lib_make_reverse_iterator should have the value 201402L in c++2b" # endif +# ifndef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should be defined in c++2b" +# endif +# if __cpp_lib_move_iterator_concept != 202207L +# error "__cpp_lib_move_iterator_concept should have the value 202207L in c++2b" +# endif + # ifndef __cpp_lib_nonmember_container_access # error "__cpp_lib_nonmember_container_access should be defined in c++2b" # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -116,6 +116,7 @@ __cpp_lib_math_constants 201907L [C++20] __cpp_lib_math_special_functions 201603L [C++17] __cpp_lib_memory_resource 201603L [C++17] + __cpp_lib_move_iterator_concept 202207L [C++20] __cpp_lib_move_only_function 202110L [C++2b] __cpp_lib_node_extract 201606L [C++17] __cpp_lib_nonmember_container_access 201411L [C++17] @@ -578,6 +579,10 @@ # error "__cpp_lib_memory_resource should not be defined before c++17" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++20" +# endif + # ifdef __cpp_lib_move_only_function # error "__cpp_lib_move_only_function should not be defined before c++2b" # endif @@ -1250,6 +1255,10 @@ # error "__cpp_lib_memory_resource should not be defined before c++17" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++20" +# endif + # ifdef __cpp_lib_move_only_function # error "__cpp_lib_move_only_function should not be defined before c++2b" # endif @@ -2072,6 +2081,10 @@ # error "__cpp_lib_memory_resource should have the value 201603L in c++17" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++20" +# endif + # ifdef __cpp_lib_move_only_function # error "__cpp_lib_move_only_function should not be defined before c++2b" # endif @@ -3176,6 +3189,13 @@ # error "__cpp_lib_memory_resource should have the value 201603L in c++20" # endif +# ifndef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should be defined in c++20" +# endif +# if __cpp_lib_move_iterator_concept != 202207L +# error "__cpp_lib_move_iterator_concept should have the value 202207L in c++20" +# endif + # ifdef __cpp_lib_move_only_function # error "__cpp_lib_move_only_function should not be defined before c++2b" # endif @@ -4415,6 +4435,13 @@ # error "__cpp_lib_memory_resource should have the value 201603L in c++2b" # endif +# ifndef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should be defined in c++2b" +# endif +# if __cpp_lib_move_iterator_concept != 202207L +# error "__cpp_lib_move_iterator_concept should have the value 202207L in c++2b" +# endif + # if !defined(_LIBCPP_VERSION) # ifndef __cpp_lib_move_only_function # error "__cpp_lib_move_only_function should be defined in c++2b" diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -488,6 +488,10 @@ "values": { "c++17": 201603 }, "headers": ["memory_resource"], }, { + "name": "__cpp_lib_move_iterator_concept", + "values": { "c++20": 202207 }, + "headers": ["iterator"], + }, { "name": "__cpp_lib_move_only_function", "values": { "c++2b": 202110 }, "headers": ["functional"],