On Tue, 4 Oct 2022, Jonathan Wakely wrote: > On Tue, 4 Oct 2022 at 02:11, Patrick Palka via Libstdc++ > <libstd...@gcc.gnu.org> wrote: > > > > Tested on x86_64-pc-linux-gnu, does this look OK for trunk? FWIW using > > OK, thanks.
Thanks a lot, patch committed. > > > variant<_PatternIter, _InnerIter> in the implementation means we need to > > include <variant> from <ranges>, which increases the preprocessed size > > of <ranges> by 3% (51.5k vs 53k). I suppose that's an acceptable cost? > > Yeah, I don't think we want to reimplement a lightweight std::variant, > because that would just add even more code. Sounds good. > > As I mentioned on IRC, maybe we could optimize the compilation time > for some of the visitation using P2637R0, but that can be done later. Ah, I didn't consider the compile time impact of using std::visit. Since we already use/instantiate std::get elsewhere in the implementation, what do you think about doing the visitation manually via index() and std::get like so? Seems to reduce compile time/memory usage for join_with/1.cc by around 6% and doesn't look too messy since we're dealing with only two alternatives. (And IIUC this should be equivalent to std::visit wrt valueless_by_exception handling, since the call to std::get<1> in each else branch will throw bad_variant_access for us like std::visit would.) -- >8 -- Subject: [PATCH] libstdc++: Avoid std::visit in ranges::join_with_view libstdc++-v3/ChangeLog: * include/std/ranges (join_with_view::_Iterator::operator*): Replace use of std::visit with manual visitation. (join_with_view::_Iterator::operator++): Likewise. (join_with_view::_Iterator::operator--): Likewise. (join_with_view::_Iterator::iter_move): Likewise. (join_with_view::_Iterator::iter_swap): Likewise. --- libstdc++-v3/include/std/ranges | 47 +++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index d0d6ce61a87..1f821128d2d 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -7165,18 +7165,23 @@ namespace views::__adaptor _M_inner_it.template emplace<1>(std::get<1>(std::move(__i._M_inner_it))); } - constexpr decltype(auto) + constexpr common_reference_t<iter_reference_t<_InnerIter>, + iter_reference_t<_PatternIter>> operator*() const { - using reference = common_reference_t<iter_reference_t<_InnerIter>, - iter_reference_t<_PatternIter>>; - return std::visit([](auto& __it) -> reference { return *__it; }, _M_inner_it); + if (_M_inner_it.index() == 0) + return *std::get<0>(_M_inner_it); + else + return *std::get<1>(_M_inner_it); } constexpr _Iterator& operator++() { - std::visit([](auto& __it){ ++__it; }, _M_inner_it); + if (_M_inner_it.index() == 0) + ++std::get<0>(_M_inner_it); + else + ++std::get<1>(_M_inner_it); _M_satisfy(); return *this; } @@ -7232,7 +7237,10 @@ namespace views::__adaptor } } - std::visit([](auto& __it){ --__it; }, _M_inner_it); + if (_M_inner_it.index() == 0) + --std::get<0>(_M_inner_it); + else + --std::get<1>(_M_inner_it); return *this; } @@ -7253,18 +7261,35 @@ namespace views::__adaptor && equality_comparable<_OuterIter> && equality_comparable<_InnerIter> { return __x._M_outer_it == __y._M_outer_it && __x._M_inner_it ==__y._M_inner_it; } - friend constexpr decltype(auto) + friend constexpr common_reference_t<iter_rvalue_reference_t<_InnerIter>, + iter_rvalue_reference_t<_PatternIter>> iter_move(const _Iterator& __x) { - using __rval_ref = common_reference_t<iter_rvalue_reference_t<_InnerIter>, - iter_rvalue_reference_t<_PatternIter>>; - return std::visit<__rval_ref>(ranges::iter_move, __x._M_inner_it); + if (__x._M_inner_it.index() == 0) + return ranges::iter_move(std::get<0>(__x._M_inner_it)); + else + return ranges::iter_move(std::get<1>(__x._M_inner_it)); } friend constexpr void iter_swap(const _Iterator& __x, const _Iterator& __y) requires indirectly_swappable<_InnerIter, _PatternIter> - { std::visit(ranges::iter_swap, __x._M_inner_it, __y._M_inner_it); } + { + if (__x._M_inner_it.index() == 0) + { + if (__y._M_inner_it.index() == 0) + ranges::iter_swap(std::get<0>(__x._M_inner_it), std::get<0>(__y._M_inner_it)); + else + ranges::iter_swap(std::get<0>(__x._M_inner_it), std::get<1>(__y._M_inner_it)); + } + else + { + if (__y._M_inner_it.index() == 0) + ranges::iter_swap(std::get<1>(__x._M_inner_it), std::get<0>(__y._M_inner_it)); + else + ranges::iter_swap(std::get<1>(__x._M_inner_it), std::get<1>(__y._M_inner_it)); + } + } }; template<input_range _Vp, forward_range _Pattern> -- 2.38.0.rc2