33 #include <ableton/build_system/Warnings.hpp>
35 #include <boost/range/iterator_range.hpp>
36 #include <boost/iterator/iterator_facade.hpp>
37 #include <boost/optional.hpp>
38 #include <boost/mpl/eval_if.hpp>
48 template <
typename ValueT,
typename XformT,
typename... IteratorTs>
52 using cache_t = std::vector<value_t>;
53 using state_t = sequence_data*;
57 template <
typename... Ts>
58 state_t operator() (state_t s, Ts&& ...xs)
60 s->impl_.cache.emplace_back(std::forward<Ts>(xs)...);
65 using reductor_t = reductor_fn<
66 estd::decay_t<estd::result_of_t<XformT(step_t)> >,
68 meta::value_t<IteratorTs>... >;
70 template <
typename... RangeTs>
71 sequence_data(XformT xform,
const RangeTs& ...ranges)
76 std::move(xform)(step_t{}),
78 *std::begin(ranges)...},
79 std::make_tuple(++std::begin(ranges)...),
80 std::make_tuple(std::end(ranges)...)
86 sequence_data(sequence_data&& other)
87 : impl_(
std::move(other.impl_))
88 { impl_.reductor.current(
this); }
90 sequence_data(
const sequence_data& other)
92 { impl_.reductor.current(
this); }
94 sequence_data& operator=(sequence_data&& other)
96 impl_ = std::move(other.impl);
97 impl_.reductor.current(
this);
100 sequence_data& operator=(
const sequence_data& other)
103 sequence_data copied{ other };
110 return impl_.pos == impl_.cache.size() && (
112 !detail::tuple_all_neq(impl_.firsts, impl_.lasts));
115 const value_t& front()
const
117 return impl_.cache[impl_.pos];
126 bool operator==(
const sequence_data& other)
const
128 return impl_.firsts == other.impl_.firsts
129 && impl_.pos == other.impl_.pos;
132 bool operator!=(
const sequence_data& other)
const
133 {
return !(*
this == other); }
137 { pull(estd::make_index_sequence<
sizeof...(IteratorTs)>{}); }
139 template <std::size_t... Indexes>
140 void pull(estd::index_sequence<Indexes...>)
142 if (impl_.pos == impl_.cache.size())
146 while (impl_.cache.empty() &&
148 detail::tuple_all_neq(impl_.firsts, impl_.lasts))
151 impl_.reductor(*get<Indexes>(impl_.firsts)...);
152 meta::noop(++get<Indexes>(impl_.firsts)...);
161 std::tuple<IteratorTs...> firsts;
162 std::tuple<IteratorTs...> lasts;
187 template <
typename ValueT,
192 using data_t = detail::sequence_data<
195 decltype(std::begin(std::declval<const RangeTs&>()))...>;
197 using value_type =
const ValueT;
201 boost::forward_traversal_tag>
205 friend class boost::iterator_core_access;
207 iterator(boost::optional<data_t> data)
208 : data_(data && !data->empty() ? data : boost::none)
218 bool equal(
const iterator& other)
const
219 {
return data_ == other.data_; }
221 const value_type& dereference()
const
222 {
return data_->front(); }
224 boost::optional<data_t> data_;
228 : xform_(
std::move(xform))
232 using const_iterator = iterator;
234 iterator begin()
const {
return { make_data() }; }
235 iterator end()
const {
return { boost::none }; }
238 boost::optional<data_t> make_data()
const
239 {
return make_data(estd::make_index_sequence<
sizeof...(RangeTs)>{}); }
241 template <std::size_t... Indexes>
242 boost::optional<data_t> make_data(estd::index_sequence<Indexes...>)
const
244 return detail::tuple_all_neq(
245 std::make_tuple(std::begin(std::get<Indexes>(ranges_))...),
246 std::make_tuple(std::end(std::get<Indexes>(ranges_))...))
247 ? boost::make_optional(data_t { xform_, std::get<Indexes>(ranges_)... })
252 std::tuple<
const RangeTs&...> ranges_;
256 struct deduce_value_type {};
265 template <
typename ValueT = detail::deduce_value_type,
268 auto sequence(XformT&& xform,
const RangeTs&... ranges)
270 typename boost::mpl::eval_if<
271 std::is_same<ValueT, detail::deduce_value_type>,
277 return { std::forward<XformT>(xform), ranges... };
typename std::decay< T >::type decay_t
Similar to C++14 std::decay_t.
C++ amazing templates and reusable implementations awesomeness.