diff --git a/libcxx/docs/Cxx2aStatusIssuesStatus.csv b/libcxx/docs/Cxx2aStatusIssuesStatus.csv --- a/libcxx/docs/Cxx2aStatusIssuesStatus.csv +++ b/libcxx/docs/Cxx2aStatusIssuesStatus.csv @@ -246,7 +246,7 @@ "`3323 <https://wg21.link/LWG3323>`__","``*has-tuple-element*``\ helper concept needs ``convertible_to``\ ","Prague","","" "`3324 <https://wg21.link/LWG3324>`__","Special-case ``std::strong/weak/partial_order``\ for pointers","Prague","","" "`3325 <https://wg21.link/LWG3325>`__","Constrain return type of transformation function for ``transform_view``\ ","Prague","","" -"`3326 <https://wg21.link/LWG3326>`__","``enable_view``\ has false positives","Prague","","" +"`3326 <https://wg21.link/LWG3326>`__","``enable_view``\ has false positives","Prague","|In progress|","" "`3327 <https://wg21.link/LWG3327>`__","Format alignment specifiers vs. text direction","Prague","","" "`3328 <https://wg21.link/LWG3328>`__","Clarify that ``std::string``\ is not good for UTF-8","Prague","","" "`3329 <https://wg21.link/LWG3329>`__","``totally_ordered_with``\ both directly and indirectly requires ``common_reference_with``\ ","Prague","|Complete|","13.0" diff --git a/libcxx/include/__ranges/concepts.h b/libcxx/include/__ranges/concepts.h --- a/libcxx/include/__ranges/concepts.h +++ b/libcxx/include/__ranges/concepts.h @@ -10,6 +10,9 @@ #define _LIBCPP_RANGES_CONCEPTS_H #include <__config> +#include <__iterator/concepts.h> +#include <__ranges/access.h> +#include <__ranges/view.h> #include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -50,6 +53,18 @@ template <range _Rp> using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<_Rp> >; + // [range.view], views + + // `enable_view` defined in <__ranges/view.h> + // `view_base` defined in <__ranges/view.h> + + template <class _Tp> + concept view = + range<_Tp> && + movable<_Tp> && + default_initializable<_Tp> && + enable_view<_Tp>; + // [range.refinements], other range refinements template <class _Tp> concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp> >; diff --git a/libcxx/include/__ranges/view.h b/libcxx/include/__ranges/view.h --- a/libcxx/include/__ranges/view.h +++ b/libcxx/include/__ranges/view.h @@ -11,7 +11,6 @@ #define _LIBCPP___RANGES_VIEW_H #include <__config> -#include <__ranges/concepts.h> #include <concepts> @@ -33,13 +32,6 @@ template <class _Tp> inline constexpr bool enable_view = derived_from<_Tp, view_base>; -template <class _Tp> -concept view = - range<_Tp> && - movable<_Tp> && - default_initializable<_Tp> && - enable_view<_Tp>; - } // end namespace ranges #endif // !_LIBCPP_HAS_NO_RANGES diff --git a/libcxx/include/span b/libcxx/include/span --- a/libcxx/include/span +++ b/libcxx/include/span @@ -22,6 +22,10 @@ template <class ElementType, size_t Extent = dynamic_extent> class span; +template<class ElementType, size_t Extent> + inline constexpr bool ranges::enable_view<span<ElementType, Extent>> = Extent == 0 || + Extent == dynamic_extent; + template<class ElementType, size_t Extent> inline constexpr bool ranges::enable_borrowed_range<span<ElementType, Extent>> = true; @@ -126,6 +130,7 @@ #include <__config> #include <__ranges/enable_borrowed_range.h> +#include <__ranges/view.h> #include <array> // for array #include <cstddef> // for byte #include <iterator> // for iterators @@ -528,6 +533,9 @@ }; #if !defined(_LIBCPP_HAS_NO_RANGES) +template <class _ElementType, size_t _Extent> +inline constexpr bool ranges::enable_view<span<_ElementType, _Extent>> = _Extent == 0 || _Extent == dynamic_extent; + template <class _Tp, size_t _Extent> inline constexpr bool ranges::enable_borrowed_range<span<_Tp, _Extent> > = true; #endif // !defined(_LIBCPP_HAS_NO_RANGES) diff --git a/libcxx/include/string_view b/libcxx/include/string_view --- a/libcxx/include/string_view +++ b/libcxx/include/string_view @@ -19,6 +19,9 @@ template<class charT, class traits = char_traits<charT>> class basic_string_view; + template<class charT, class traits> + inline constexpr bool ranges::enable_view<basic_string_view<charT, traits>> = true; + template<class charT, class traits> inline constexpr bool ranges::enable_borrowed_range<basic_string_view<charT, traits>> = true; // C++20 @@ -183,6 +186,7 @@ #include <__config> #include <__ranges/enable_borrowed_range.h> +#include <__ranges/view.h> #include <__string> #include <iosfwd> #include <algorithm> @@ -654,6 +658,9 @@ }; #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES) +template<class _CharT, class _Traits> +inline constexpr bool ranges::enable_view<basic_string_view<_CharT, _Traits>> = true; + template <class _CharT, class _Traits> inline constexpr bool ranges::enable_borrowed_range<basic_string_view<_CharT, _Traits> > = true; #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES) diff --git a/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp @@ -23,9 +23,9 @@ static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>); static_assert(stdr::common_range<range>); static_assert(stdr::random_access_range<range>); -static_assert(!stdr::view<range>); +static_assert(stdr::view<range> && stdr::enable_view<range>); static_assert(std::same_as<stdr::iterator_t<range const>, range::iterator>); static_assert(stdr::common_range<range const>); static_assert(stdr::random_access_range<range const>); -static_assert(!stdr::view<range const>); +static_assert(!stdr::view<range const> && !stdr::enable_view<range const>); diff --git a/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp @@ -22,9 +22,9 @@ static_assert(std::same_as<stdr::iterator_t<std::string_view>, std::string_view::iterator>); static_assert(stdr::common_range<std::string_view>); static_assert(stdr::random_access_range<std::string_view>); -static_assert(!stdr::view<std::string_view>); +static_assert(stdr::view<std::string_view> && stdr::enable_view<std::string_view>); static_assert(std::same_as<stdr::iterator_t<std::string_view const>, std::string_view::const_iterator>); static_assert(stdr::common_range<std::string_view const>); static_assert(stdr::random_access_range<std::string_view const>); -static_assert(!stdr::view<std::string_view const>); +static_assert(!stdr::view<std::string_view const> && !stdr::enable_view<std::string_view const>);