On Mon, 13 Jul 2026 at 16:24, Patrick Palka <[email protected]> wrote:
>
> Tested on x86_64-pc-linux-gnu, does this look OK for trunk/16?  I tried
> for a bit to contrive a testcase for this change but concluded it's not
> worth it.  What's more important is that this change doesn't break
> idiomatic uses of join_with_view which should already be covered by
> existing tests.

OK for trunk and 16


>
> -- >8 --
>
> libstdc++-v3/ChangeLog:
>
>         * include/std/ranges (__detail::__compatible_joinable_ranges):
>         Remove.
>         (__detail::__concat_reference_t): Move definition up.
>         (__detail::__concat_value_t): Likewise.
>         (__detail::__concat_rvalue_reference_t): Likewise.
>         (__detail::__concat_indirectly_readable_impl): Likewise.
>         (__detail::__concat_indirectly_readable): Likewise.
>         (__detail::__concatable): Likewise.
>         (join_with_view): Use __concatable instead of
>         __compatible_joinable_ranges in constraints as per LWG 4074.
>         (join_with_view::begin): Add __concatable constraint as per
>         LWG 4074.
>         (join_with_view::end): Likewise.
>         (join_with_view::_Iterator): Adjust out-of-line declaration.
>         (join_with_view::_Sentinel): Likewise.
> ---
>  libstdc++-v3/include/std/ranges | 86 +++++++++++++++------------------
>  1 file changed, 40 insertions(+), 46 deletions(-)
>
> diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
> index 39a50b03e457..87c443c729b9 100644
> --- a/libstdc++-v3/include/std/ranges
> +++ b/libstdc++-v3/include/std/ranges
> @@ -7363,22 +7363,49 @@ namespace views::__adaptor
>  #ifdef __cpp_lib_ranges_join_with // C++ >= 23
>    namespace __detail
>    {
> -    template<typename _Range, typename _Pattern>
> -      concept __compatible_joinable_ranges
> -       = common_with<range_value_t<_Range>, range_value_t<_Pattern>>
> -         && common_reference_with<range_reference_t<_Range>,
> -                                  range_reference_t<_Pattern>>
> -         && common_reference_with<range_rvalue_reference_t<_Range>,
> -                                  range_rvalue_reference_t<_Pattern>>;
> -
>      template<typename _Range>
>        concept __bidirectional_common = bidirectional_range<_Range> && 
> common_range<_Range>;
> +
> +    template<typename... _Rs>
> +      using __concat_reference_t = 
> common_reference_t<range_reference_t<_Rs>...>;
> +
> +    template<typename... _Rs>
> +      using __concat_value_t = common_type_t<range_value_t<_Rs>...>;
> +
> +    template<typename... _Rs>
> +      using __concat_rvalue_reference_t
> +       = common_reference_t<range_rvalue_reference_t<_Rs>...>;
> +
> +    template<typename _Ref, typename _RRef, typename _It>
> +      concept __concat_indirectly_readable_impl = requires(const _It __it) {
> +       { *__it } -> convertible_to<_Ref>;
> +       { ranges::iter_move(__it) } -> convertible_to<_RRef>;
> +      };
> +
> +    template<typename... _Rs>
> +      concept __concat_indirectly_readable
> +       = common_reference_with<__concat_reference_t<_Rs...>&&, 
> __concat_value_t<_Rs...>&>
> +         && common_reference_with<__concat_reference_t<_Rs...>&&,
> +                                  __concat_rvalue_reference_t<_Rs...>&&>
> +         && common_reference_with<__concat_rvalue_reference_t<_Rs...>&&,
> +                                  __concat_value_t<_Rs...> const&>
> +         && (__concat_indirectly_readable_impl<__concat_reference_t<_Rs...>,
> +                                               
> __concat_rvalue_reference_t<_Rs...>,
> +                                               iterator_t<_Rs>>
> +             && ...);
> +
> +    template<typename... _Rs>
> +      concept __concatable = requires {
> +       typename __concat_reference_t<_Rs...>;
> +       typename __concat_value_t<_Rs...>;
> +       typename __concat_rvalue_reference_t<_Rs...>;
> +      } && __concat_indirectly_readable<_Rs...>;
>    }
>
>    template<input_range _Vp, forward_range _Pattern>
>      requires view<_Vp> && view<_Pattern>
>        && input_range<range_reference_t<_Vp>>
> -      && __detail::__compatible_joinable_ranges<range_reference_t<_Vp>, 
> _Pattern>
> +      && __detail::__concatable<range_reference_t<_Vp>, _Pattern>
>    class join_with_view : public view_interface<join_with_view<_Vp, _Pattern>>
>    {
>      using _InnerRange = range_reference_t<_Vp>;
> @@ -7495,6 +7522,7 @@ namespace views::__adaptor
>         && forward_range<const _Pattern>
>         && is_reference_v<range_reference_t<const _Vp>>
>         && input_range<range_reference_t<const _Vp>>
> +       && __detail::__concatable<range_reference_t<const _Vp>, const 
> _Pattern>
>      { return _Iterator<true>{*this, ranges::begin(_M_base)}; }
>
>      constexpr auto
> @@ -7516,6 +7544,7 @@ namespace views::__adaptor
>         && forward_range<const _Pattern>
>         && is_reference_v<range_reference_t<const _Vp>>
>         && input_range<range_reference_t<const _Vp>>
> +       && __detail::__concatable<range_reference_t<const _Vp>, const 
> _Pattern>
>      {
>        using _InnerConstRange = range_reference_t<const _Vp>;
>        if constexpr (forward_range<_InnerConstRange>
> @@ -7539,7 +7568,7 @@ namespace views::__adaptor
>    template<input_range _Vp, forward_range _Pattern>
>      requires view<_Vp> && view<_Pattern>
>        && input_range<range_reference_t<_Vp>>
> -      && __detail::__compatible_joinable_ranges<range_reference_t<_Vp>, 
> _Pattern>
> +      && __detail::__concatable<range_reference_t<_Vp>, _Pattern>
>    template<bool _Const>
>    class join_with_view<_Vp, _Pattern>::_Iterator : public __iter_cat<_Const>
>    {
> @@ -7828,7 +7857,7 @@ namespace views::__adaptor
>    template<input_range _Vp, forward_range _Pattern>
>      requires view<_Vp> && view<_Pattern>
>        && input_range<range_reference_t<_Vp>>
> -      && __detail::__compatible_joinable_ranges<range_reference_t<_Vp>, 
> _Pattern>
> +      && __detail::__concatable<range_reference_t<_Vp>, _Pattern>
>    template<bool _Const>
>    class join_with_view<_Vp, _Pattern>::_Sentinel
>    {
> @@ -9804,41 +9833,6 @@ namespace ranges
>  {
>    namespace __detail
>    {
> -    template<typename... _Rs>
> -      using __concat_reference_t = 
> common_reference_t<range_reference_t<_Rs>...>;
> -
> -    template<typename... _Rs>
> -      using __concat_value_t = common_type_t<range_value_t<_Rs>...>;
> -
> -    template<typename... _Rs>
> -      using __concat_rvalue_reference_t
> -       = common_reference_t<range_rvalue_reference_t<_Rs>...>;
> -
> -    template<typename _Ref, typename _RRef, typename _It>
> -      concept __concat_indirectly_readable_impl = requires(const _It __it) {
> -       { *__it } -> convertible_to<_Ref>;
> -       { ranges::iter_move(__it) } -> convertible_to<_RRef>;
> -      };
> -
> -    template<typename... _Rs>
> -      concept __concat_indirectly_readable
> -       = common_reference_with<__concat_reference_t<_Rs...>&&, 
> __concat_value_t<_Rs...>&>
> -         && common_reference_with<__concat_reference_t<_Rs...>&&,
> -                                  __concat_rvalue_reference_t<_Rs...>&&>
> -         && common_reference_with<__concat_rvalue_reference_t<_Rs...>&&,
> -                                  __concat_value_t<_Rs...> const&>
> -         && (__concat_indirectly_readable_impl<__concat_reference_t<_Rs...>,
> -                                               
> __concat_rvalue_reference_t<_Rs...>,
> -                                               iterator_t<_Rs>>
> -             && ...);
> -
> -    template<typename... _Rs>
> -      concept __concatable = requires {
> -       typename __concat_reference_t<_Rs...>;
> -       typename __concat_value_t<_Rs...>;
> -       typename __concat_rvalue_reference_t<_Rs...>;
> -      } && __concat_indirectly_readable<_Rs...>;
> -
>      template<bool _Const, typename _Range, typename... _Rs>
>        struct __all_but_last_common
>        {
> --
> 2.55.0.122.gf85a7e6620
>

Reply via email to