Skip to content

Commit

Permalink
Joining all views of ranges. (#1655)
Browse files Browse the repository at this point in the history
  • Loading branch information
brevzin committed Feb 18, 2022
1 parent b832d51 commit d800a03
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 30 deletions.
25 changes: 25 additions & 0 deletions include/range/v3/utility/optional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,17 @@ namespace ranges
engaged_ = true;
return data_;
}
template(typename I)(
/// \pre
requires constructible_from<T, decltype(*std::declval<const I &>())>)
T & construct_from_deref(const I & it)
{
RANGES_EXPECT(!engaged_);
auto const address = static_cast<void *>(std::addressof(data_));
::new(address) T(*it);
engaged_ = true;
return data_;
}
template<typename U>
constexpr void assign_from(U && that) noexcept(
std::is_nothrow_constructible<T, decltype(*static_cast<U &&>(that))>::
Expand Down Expand Up @@ -650,6 +661,15 @@ namespace ranges
return *this;
}

template(typename I)(
/// \pre
requires constructible_from<T, decltype(*std::declval<const I &>())>)
T & emplace_deref(const I & it)
{
reset();
return base_t::construct_from_deref(it);
}

template(typename... Args)(
/// \pre
requires constructible_from<T, Args...>)
Expand Down Expand Up @@ -978,6 +998,11 @@ namespace ranges
return *this;
}
using optional<T>::operator=;
template<class I>
constexpr T & emplace_deref(const I & i)
{
return optional<T>::emplace(*i);
}
};

template<typename T, typename Tag>
Expand Down
50 changes: 23 additions & 27 deletions include/range/v3/view/join.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,25 +80,26 @@ namespace ranges
template<typename Inner>
struct store_inner_
{
views::all_t<Inner> inner_ = views::all_t<Inner>();
non_propagating_cache<std::remove_cv_t<Inner>> inner_ = {};

constexpr views::all_t<Inner> & update_inner_(Inner && inner)
template<typename OuterIt>
constexpr auto && update_inner_(OuterIt && it)
{
return (inner_ = views::all(static_cast<Inner &&>(inner)));
return inner_.emplace_deref(it);
}
constexpr views::all_t<Inner> & get_inner_(ignore_t) noexcept
constexpr Inner & get_inner_(ignore_t) noexcept
{
return inner_;
return *inner_;
}
};

struct pass_thru_inner_
{
// Intentionally promote xvalues to lvalues here:
template<typename Inner>
static constexpr Inner & update_inner_(Inner && inner) noexcept
template<typename OuterIt>
static constexpr auto && update_inner_(OuterIt && it) noexcept
{
return inner;
return *it;
}
template<typename OuterIt>
static constexpr decltype(auto) get_inner_(OuterIt && outer_it)
Expand Down Expand Up @@ -139,8 +140,6 @@ namespace ranges
{
CPP_assert(input_range<Rng> && view_<Rng>);
CPP_assert(input_range<range_reference_t<Rng>>);
CPP_assert(std::is_reference<range_reference_t<Rng>>::value ||
view_<range_reference_t<Rng>>);

join_view() = default;
explicit join_view(Rng rng)
Expand Down Expand Up @@ -196,7 +195,7 @@ namespace ranges
{
for(; outer_it_ != ranges::end(rng_->outer_); ++outer_it_)
{
auto & inner = rng_->update_inner_(*outer_it_);
auto && inner = rng_->update_inner_(outer_it_);
inner_it_ = ranges::begin(inner);
if(inner_it_ != ranges::end(inner))
return;
Expand Down Expand Up @@ -356,6 +355,7 @@ namespace ranges
template<typename Rng, typename ValRng>
struct join_with_view
: view_facade<join_with_view<Rng, ValRng>, detail::join_cardinality<Rng, ValRng>()>
, private detail::join_view_inner<Rng>
{
CPP_assert(input_range<Rng>);
CPP_assert(input_range<range_reference_t<Rng>>);
Expand Down Expand Up @@ -399,7 +399,6 @@ namespace ranges
using Inner = views::all_t<range_reference_t<Outer> &>;

Outer outer_{};
Inner inner_{};
views::all_t<ValRng> val_{};

class cursor
Expand All @@ -417,13 +416,13 @@ namespace ranges
if(ranges::get<0>(cur_) != ranges::end(rng_->val_))
break;
// Intentionally promote xvalues to lvalues here:
auto && tmp = *outer_it_;
rng_->inner_ = views::all(tmp);
ranges::emplace<1>(cur_, ranges::begin(rng_->inner_));
auto && inner = rng_->update_inner_(outer_it_);
ranges::emplace<1>(cur_, ranges::begin(inner));
}
else
{
if(ranges::get<1>(cur_) != ranges::end(rng_->inner_))
auto && inner = rng_->get_inner_(outer_it_);
if(ranges::get<1>(cur_) != ranges::end(inner))
break;
if(++outer_it_ == ranges::end(rng_->outer_))
break;
Expand All @@ -446,10 +445,8 @@ namespace ranges
{
if(outer_it_ != ranges::end(rng->outer_))
{
// Intentionally promote xvalues to lvalues here:
auto && tmp = *outer_it_;
rng->inner_ = views::all(tmp);
ranges::emplace<1>(cur_, ranges::begin(rng->inner_));
auto && inner = rng_->update_inner_(outer_it_);
ranges::emplace<1>(cur_, ranges::begin(inner));
satisfy();
}
}
Expand All @@ -469,7 +466,10 @@ namespace ranges
else
{
auto & it = ranges::get<1>(cur_);
RANGES_ASSERT(it != ranges::end(rng_->inner_));
#ifndef NDEBUG
auto && inner = rng_->get_inner_(outer_it_);
RANGES_ASSERT(it != ranges::end(inner));
#endif
++it;
}
satisfy();
Expand Down Expand Up @@ -506,9 +506,7 @@ namespace ranges
// clang-format off
template(typename Rng)(
concept (joinable_range_)(Rng),
input_range<range_reference_t<Rng>> AND
(std::is_reference<range_reference_t<Rng>>::value ||
view_<range_reference_t<Rng>>)
input_range<range_reference_t<Rng>>
);
template<typename Rng>
CPP_concept joinable_range =
Expand Down Expand Up @@ -642,9 +640,7 @@ namespace ranges
template(typename Rng)(
/// \pre
requires input_range<Rng> AND view_<Rng> AND
input_range<iter_reference_t<iterator_t<Rng>>> AND
(std::is_reference<iter_reference_t<iterator_t<Rng>>>::value ||
view_<iter_value_t<iterator_t<Rng>>>)) //
input_range<iter_reference_t<iterator_t<Rng>>>) //
using join_view = ranges::join_view<Rng>;
} // namespace cpp20
} // namespace ranges
Expand Down
3 changes: 0 additions & 3 deletions test/view/join.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include <range/v3/view/split.hpp>
#include <range/v3/view/generate_n.hpp>
#include <range/v3/view/repeat_n.hpp>
#include <range/v3/view/cache1.hpp>
#include <range/v3/view/chunk.hpp>
#include <range/v3/view/concat.hpp>
#include <range/v3/view/iota.hpp>
Expand Down Expand Up @@ -220,7 +219,6 @@ int main()
{
auto rng = views::iota(0,4)
| views::transform([](int i) {return std::string((std::size_t) i, char('a'+i));})
| views::cache1
| views::join;
check_equal(rng, {'b','c','c','d','d','d'});
CPP_assert(input_range<decltype(rng)>);
Expand All @@ -232,7 +230,6 @@ int main()
{
auto rng = views::iota(0,4)
| views::transform([](int i) {return std::string((std::size_t) i, char('a'+i));})
| views::cache1
| views::join('-');
check_equal(rng, {'-','b','-','c','c','-','d','d','d'});
CPP_assert(input_range<decltype(rng)>);
Expand Down

0 comments on commit d800a03

Please sign in to comment.