diff --git a/libcxx/include/__format/format_functions.h b/libcxx/include/__format/format_functions.h --- a/libcxx/include/__format/format_functions.h +++ b/libcxx/include/__format/format_functions.h @@ -38,7 +38,9 @@ #include <__format/formatter_string.h> #include <__format/parser_std_format_spec.h> #include <__iterator/back_insert_iterator.h> +#include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> +#include <__iterator/readable_traits.h> // iter_value_t #include <__variant/monostate.h> #include #include @@ -236,21 +238,22 @@ std::__throw_format_error("Invalid argument"); } -template -_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* -__handle_replacement_field(const _CharT* __begin, const _CharT* __end, +template +_LIBCPP_HIDE_FROM_ABI constexpr _Iterator +__handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __parse_ctx, _Ctx& __ctx) { + using _CharT = iter_value_t<_Iterator>; __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx); - bool __parse = *__r.__ptr == _CharT(':'); - switch (*__r.__ptr) { + bool __parse = *__r.__last == _CharT(':'); + switch (*__r.__last) { case _CharT(':'): // The arg-id has a format-specifier, advance the input to the format-spec. - __parse_ctx.advance_to(__r.__ptr + 1); + __parse_ctx.advance_to(__r.__last + 1); break; case _CharT('}'): // The arg-id has no format-specifier. - __parse_ctx.advance_to(__r.__ptr); + __parse_ctx.advance_to(__r.__last); break; default: std::__throw_format_error("The replacement field arg-id should terminate at a ':' or '}'"); @@ -291,8 +294,8 @@ using _CharT = typename _ParseCtx::char_type; static_assert(same_as); - const _CharT* __begin = __parse_ctx.begin(); - const _CharT* __end = __parse_ctx.end(); + auto __begin = __parse_ctx.begin(); + auto __end = __parse_ctx.end(); typename _Ctx::iterator __out_it = __ctx.out(); while (__begin != __end) { switch (*__begin) { diff --git a/libcxx/include/__format/format_string.h b/libcxx/include/__format/format_string.h --- a/libcxx/include/__format/format_string.h +++ b/libcxx/include/__format/format_string.h @@ -13,6 +13,8 @@ #include <__assert> #include <__config> #include <__format/format_error.h> +#include <__iterator/concepts.h> +#include <__iterator/readable_traits.h> // iter_value_t #include #include @@ -26,18 +28,18 @@ namespace __format { -template +template struct _LIBCPP_TEMPLATE_VIS __parse_number_result { - const _CharT* __ptr; + _Iterator __last; uint32_t __value; }; -template -__parse_number_result(const _CharT*, uint32_t) -> __parse_number_result<_CharT>; +template +__parse_number_result(_Iterator, uint32_t) -> __parse_number_result<_Iterator>; -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_number(const _CharT* __begin, const _CharT* __end); +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_number(_Iterator __begin, _Iterator __end); /** * The maximum value of a numeric argument. @@ -53,16 +55,16 @@ inline constexpr uint32_t __number_max = INT32_MAX; namespace __detail { -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_zero(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_zero(_Iterator __begin, _Iterator, auto& __parse_ctx) { __parse_ctx.check_arg_id(0); return {++__begin, 0}; // can never be larger than the maximum. } -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_automatic(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_automatic(_Iterator __begin, _Iterator, auto& __parse_ctx) { size_t __value = __parse_ctx.next_arg_id(); _LIBCPP_ASSERT(__value <= __number_max, "Compilers don't support this number of arguments"); @@ -70,10 +72,10 @@ return {__begin, uint32_t(__value)}; } -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_manual(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { - __parse_number_result<_CharT> __r = __format::__parse_number(__begin, __end); +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_manual(_Iterator __begin, _Iterator __end, auto& __parse_ctx) { + __parse_number_result<_Iterator> __r = __format::__parse_number(__begin, __end); __parse_ctx.check_arg_id(__r.__value); return __r; } @@ -86,9 +88,10 @@ * The number is used for the 31-bit values @em width and @em precision. This * allows a maximum value of 2147483647. */ -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_number(const _CharT* __begin, const _CharT* __end_input) { +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_number(_Iterator __begin, _Iterator __end_input) { + using _CharT = iter_value_t<_Iterator>; static_assert(__format::__number_max == INT32_MAX, "The algorithm is implemented based on this value."); /* @@ -98,7 +101,7 @@ * - Does the value exceed width of an uint32_t? (Switching to uint64_t would * have the same issue, but with a higher maximum.) */ - const _CharT* __end = __end_input - __begin > 9 ? __begin + 9 : __end_input; + _Iterator __end = __end_input - __begin > 9 ? __begin + 9 : __end_input; uint32_t __value = *__begin - _CharT('0'); while (++__begin != __end) { if (*__begin < _CharT('0') || *__begin > _CharT('9')) @@ -134,9 +137,10 @@ * The parser will return a pointer beyond the last consumed character. This * should be the closing '}' of the arg-id. */ -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_arg_id(_Iterator __begin, _Iterator __end, auto& __parse_ctx) { + using _CharT = iter_value_t<_Iterator>; switch (*__begin) { case _CharT('0'): return __detail::__parse_zero(__begin, __end, __parse_ctx); diff --git a/libcxx/include/__format/formatter_output.h b/libcxx/include/__format/formatter_output.h --- a/libcxx/include/__format/formatter_output.h +++ b/libcxx/include/__format/formatter_output.h @@ -23,6 +23,8 @@ #include <__format/parser_std_format_spec.h> #include <__format/unicode.h> #include <__iterator/back_insert_iterator.h> +#include <__iterator/concepts.h> +#include <__iterator/readable_traits.h> // iter_value_t #include <__type_traits/make_unsigned.h> #include <__utility/move.h> #include <__utility/unreachable.h> @@ -261,11 +263,11 @@ return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); } -template +template _LIBCPP_HIDE_FROM_ABI auto -__write(const _CharT* __first, - const _CharT* __last, - output_iterator auto __out_it, +__write(_Iterator __first, + _Iterator __last, + output_iterator&> auto __out_it, __format_spec::__parsed_specifications<_ParserCharT> __specs, ptrdiff_t __size) -> decltype(__out_it) { _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); @@ -275,11 +277,11 @@ /// \overload /// /// Calls the function above where \a __size = \a __last - \a __first. -template +template _LIBCPP_HIDE_FROM_ABI auto -__write(const _CharT* __first, - const _CharT* __last, - output_iterator auto __out_it, +__write(_Iterator __first, + _Iterator __last, + output_iterator&> auto __out_it, __format_spec::__parsed_specifications<_ParserCharT> __specs) -> decltype(__out_it) { _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); return __formatter::__write(__first, __last, _VSTD::move(__out_it), __specs, __last - __first); @@ -359,7 +361,7 @@ template _LIBCPP_HIDE_FROM_ABI int __truncate(basic_string_view<_CharT>& __str, int __precision) { - __format_spec::__column_width_result<_CharT> __result = + __format_spec::__column_width_result __result = __format_spec::__estimate_column_width(__str, __precision, __format_spec::__column_width_rounding::__down); __str = basic_string_view<_CharT>{__str.begin(), __result.__last_}; return __result.__width_; diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h --- a/libcxx/include/__format/parser_std_format_spec.h +++ b/libcxx/include/__format/parser_std_format_spec.h @@ -28,6 +28,8 @@ #include <__format/format_parse_context.h> #include <__format/format_string.h> #include <__format/unicode.h> +#include <__iterator/concepts.h> +#include <__iterator/readable_traits.h> // iter_value_t #include <__variant/monostate.h> #include #include @@ -47,9 +49,10 @@ namespace __format_spec { -template -_LIBCPP_HIDE_FROM_ABI constexpr __format::__parse_number_result< _CharT> -__parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { +template +_LIBCPP_HIDE_FROM_ABI constexpr __format::__parse_number_result<_Iterator> +__parse_arg_id(_Iterator __begin, _Iterator __end, auto& __parse_ctx) { + using _CharT = iter_value_t<_Iterator>; // This function is a wrapper to call the real parser. But it does the // validation for the pre-conditions and post-conditions. if (__begin == __end) @@ -57,10 +60,10 @@ __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx); - if (__r.__ptr == __end || *__r.__ptr != _CharT('}')) + if (__r.__last == __end || *__r.__last != _CharT('}')) std::__throw_format_error("Invalid arg-id"); - ++__r.__ptr; + ++__r.__last; return __r; } @@ -268,8 +271,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(basic_format_parse_context<_CharT>& __parse_ctx, __fields __fields) -> decltype(__parse_ctx.begin()) { - const _CharT* __begin = __parse_ctx.begin(); - const _CharT* __end = __parse_ctx.end(); + auto __begin = __parse_ctx.begin(); + auto __end = __parse_ctx.end(); if (__begin == __end) return __begin; @@ -391,8 +394,8 @@ } // range-fill and tuple-fill are identical - _LIBCPP_HIDE_FROM_ABI constexpr bool - __parse_fill_align(const _CharT*& __begin, const _CharT* __end, bool __use_range_fill) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_fill_align(_Iterator& __begin, _Iterator __end, bool __use_range_fill) { _LIBCPP_ASSERT(__begin != __end, "when called with an empty input the function will cause " "undefined behavior by evaluating data not in the input"); if (__begin + 1 != __end) { @@ -415,7 +418,8 @@ return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_sign(const _CharT*& __begin) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_sign(_Iterator& __begin) { switch (*__begin) { case _CharT('-'): __sign_ = __sign::__minus; @@ -433,7 +437,8 @@ return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_alternate_form(const _CharT*& __begin) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_alternate_form(_Iterator& __begin) { if (*__begin != _CharT('#')) return false; @@ -442,7 +447,8 @@ return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_zero_padding(const _CharT*& __begin) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_zero_padding(_Iterator& __begin) { if (*__begin != _CharT('0')) return false; @@ -452,7 +458,8 @@ return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_width(const _CharT*& __begin, const _CharT* __end, auto& __parse_ctx) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_width(_Iterator& __begin, _Iterator __end, auto& __parse_ctx) { if (*__begin == _CharT('0')) std::__throw_format_error("A format-spec width field shouldn't have a leading zero"); @@ -460,7 +467,7 @@ __format::__parse_number_result __r = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx); __width_as_arg_ = true; __width_ = __r.__value; - __begin = __r.__ptr; + __begin = __r.__last; return true; } @@ -471,12 +478,12 @@ __width_ = __r.__value; _LIBCPP_ASSERT(__width_ != 0, "A zero value isn't allowed and should be impossible, " "due to validations in this function"); - __begin = __r.__ptr; + __begin = __r.__last; return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_precision(const _CharT*& __begin, const _CharT* __end, - auto& __parse_ctx) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_precision(_Iterator& __begin, _Iterator __end, auto& __parse_ctx) { if (*__begin != _CharT('.')) return false; @@ -488,7 +495,7 @@ __format::__parse_number_result __arg_id = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx); __precision_as_arg_ = true; __precision_ = __arg_id.__value; - __begin = __arg_id.__ptr; + __begin = __arg_id.__last; return true; } @@ -498,11 +505,12 @@ __format::__parse_number_result __r = __format::__parse_number(__begin, __end); __precision_ = __r.__value; __precision_as_arg_ = false; - __begin = __r.__ptr; + __begin = __r.__last; return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_locale_specific_form(const _CharT*& __begin) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_locale_specific_form(_Iterator& __begin) { if (*__begin != _CharT('L')) return false; @@ -511,7 +519,8 @@ return true; } - _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(const _CharT*& __begin) { + template + _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(_Iterator& __begin) { // Determines the type. It does not validate whether the selected type is // valid. Most formatters have optional fields that are only allowed for // certain types. These parsers need to do validation after the type has @@ -734,18 +743,18 @@ } } -template +template struct __column_width_result { /// The number of output columns. size_t __width_; /// One beyond the last code unit used in the estimation. /// /// This limits the original output to fit in the wanted number of columns. - const _CharT* __last_; + _Iterator __last_; }; -template -__column_width_result(size_t, const _CharT*) -> __column_width_result<_CharT>; +template +__column_width_result(size_t, _Iterator) -> __column_width_result<_Iterator>; /// Since a column width can be two it's possible that the requested column /// width can't be achieved. Depending on the intended usage the policy can be @@ -812,12 +821,13 @@ return __detail::__column_width_4(__c); } -template -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_width_grapheme_clustering( - const _CharT* __first, const _CharT* __last, size_t __maximum, __column_width_rounding __rounding) noexcept { +template +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_Iterator> __estimate_column_width_grapheme_clustering( + _Iterator __first, _Iterator __last, size_t __maximum, __column_width_rounding __rounding) noexcept { + using _CharT = iter_value_t<_Iterator>; __unicode::__extended_grapheme_cluster_view<_CharT> __view{__first, __last}; - __column_width_result<_CharT> __result{0, __first}; + __column_width_result<_Iterator> __result{0, __first}; while (__result.__last_ != __last && __result.__width_ <= __maximum) { typename __unicode::__extended_grapheme_cluster_view<_CharT>::__cluster __cluster = __view.__consume(); int __width = __detail::__column_width(__cluster.__code_point_); @@ -884,8 +894,8 @@ /// \param __rounding Selects the rounding method. /// \c __down result.__width_ <= __maximum /// \c __up result.__width_ <= __maximum + 1 -template -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_width( +template ::const_iterator> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_Iterator> __estimate_column_width( basic_string_view<_CharT> __str, size_t __maximum, __column_width_rounding __rounding) noexcept { // The width estimation is done in two steps: // - Quickly process for the ASCII part. ASCII has the following properties @@ -904,7 +914,7 @@ // need to scan one code unit beyond the requested precision. When this code // unit is non-ASCII we omit the current code unit and let the Grapheme // clustering algorithm do its work. - const _CharT* __it = __str.begin(); + auto __it = __str.begin(); if (__format_spec::__is_ascii(*__it)) { do { --__maximum; @@ -932,7 +942,7 @@ } # else // !defined(_LIBCPP_HAS_NO_UNICODE) template -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result::const_iterator> __estimate_column_width(basic_string_view<_CharT> __str, size_t __maximum, __column_width_rounding) noexcept { // When Unicode isn't supported assume ASCII and every code unit is one code // point. In ASCII the estimated column width is always one. Thus there's no diff --git a/libcxx/include/__format/unicode.h b/libcxx/include/__format/unicode.h --- a/libcxx/include/__format/unicode.h +++ b/libcxx/include/__format/unicode.h @@ -11,11 +11,15 @@ #define _LIBCPP___FORMAT_UNICODE_H #include <__assert> +#include <__concepts/same_as.h> #include <__config> #include <__format/extended_grapheme_cluster_table.h> +#include <__iterator/concepts.h> +#include <__iterator/readable_traits.h> // iter_value_t #include <__type_traits/make_unsigned.h> #include <__utility/unreachable.h> #include +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -62,7 +66,9 @@ inline constexpr char32_t __replacement_character = U'\ufffd'; -_LIBCPP_HIDE_FROM_ABI constexpr bool __is_continuation(const char* __char, int __count) { +template + requires same_as, char> +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_continuation(_Iterator __char, int __count) { do { if ((*__char & 0b1000'0000) != 0b1000'0000) return false; @@ -82,12 +88,14 @@ /// UTF-8 specialization. template <> class __code_point_view { + using _Iterator = basic_string_view::const_iterator; + public: - _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const char* __first, const char* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) : __first_(__first), __last_(__last) {} _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } - _LIBCPP_HIDE_FROM_ABI constexpr const char* __position() const noexcept { return __first_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __position() const noexcept { return __first_; } _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); @@ -207,8 +215,8 @@ # endif // _LIBCPP_STD_VER > 20 private: - const char* __first_; - const char* __last_; + _Iterator __first_; + _Iterator __last_; }; # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -225,13 +233,15 @@ /// - 4 UTF-32 (for example Linux) template <> class __code_point_view { + using _Iterator = typename basic_string_view::const_iterator; + public: static_assert(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4, "sizeof(wchar_t) has a not implemented value"); - _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const wchar_t* __first, const wchar_t* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) : __first_(__first), __last_(__last) {} - _LIBCPP_HIDE_FROM_ABI constexpr const wchar_t* __position() const noexcept { return __first_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __position() const noexcept { return __first_; } _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { @@ -292,8 +302,8 @@ # endif // _LIBCPP_STD_VER > 20 private: - const wchar_t* __first_; - const wchar_t* __last_; + _Iterator __first_; + _Iterator __last_; }; # endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -384,8 +394,10 @@ /// Therefore only this code point is extracted. template class __extended_grapheme_cluster_view { + using _Iterator = typename basic_string_view<_CharT>::const_iterator; + public: - _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_view(const _CharT* __first, const _CharT* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_view(_Iterator __first, _Iterator __last) : __code_point_view_(__first, __last), __next_code_point_(__code_point_view_.__consume()), __next_prop_(__extended_grapheme_custer_property_boundary::__get_property(__next_code_point_)) {} @@ -401,7 +413,7 @@ /// /// It's expected the caller has the start position and thus can determine /// the code unit range of the extended grapheme cluster. - const _CharT* __last_; + _Iterator __last_; }; _LIBCPP_HIDE_FROM_ABI constexpr __cluster __consume() { @@ -422,11 +434,11 @@ char32_t __next_code_point_; __extended_grapheme_custer_property_boundary::__property __next_prop_; - _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __get_break() { + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __get_break() { bool __ri_break_allowed = true; bool __has_extened_pictographic = false; while (true) { - const _CharT* __result = __code_point_view_.__position(); + _Iterator __result = __code_point_view_.__position(); __extended_grapheme_custer_property_boundary::__property __prev = __next_prop_; if (__code_point_view_.__at_end()) { __next_prop_ = __extended_grapheme_custer_property_boundary::__property::__eot; @@ -444,8 +456,8 @@ } }; -template -__extended_grapheme_cluster_view(const _CharT*, const _CharT*) -> __extended_grapheme_cluster_view<_CharT>; +template +__extended_grapheme_cluster_view(_Iterator, _Iterator) -> __extended_grapheme_cluster_view>; # else // _LIBCPP_HAS_NO_UNICODE @@ -453,12 +465,14 @@ // This makes it easier to write code agnostic of the _LIBCPP_HAS_NO_UNICODE define. template class __code_point_view { + using _Iterator = typename basic_string_view<_CharT>::const_iterator; + public: - _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const _CharT* __first, const _CharT* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) : __first_(__first), __last_(__last) {} _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } - _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __position() const noexcept { return __first_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __position() const noexcept { return __first_; } _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); @@ -474,8 +488,8 @@ # endif // _LIBCPP_STD_VER > 20 private: - const _CharT* __first_; - const _CharT* __last_; + _Iterator __first_; + _Iterator __last_; }; # endif // _LIBCPP_HAS_NO_UNICODE diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1012,7 +1012,10 @@ module permutable { private header "__iterator/permutable.h" } module prev { private header "__iterator/prev.h" } module projected { private header "__iterator/projected.h" } - module readable_traits { private header "__iterator/readable_traits.h" } + module readable_traits { + private header "__iterator/readable_traits.h" + export __iterator.iterator_traits + } module reverse_access { private header "__iterator/reverse_access.h" } module reverse_iterator { private header "__iterator/reverse_iterator.h" } module segmented_iterator { private header "__iterator/segmented_iterator.h" }