forked from OctaForge/libostd
add initial implementation of range joiner (join any type-compatible ranges into one)
parent
59551e0aee
commit
f651940570
|
@ -5,23 +5,40 @@
|
||||||
using namespace ostd;
|
using namespace ostd;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
/* range iter */
|
/* range iter - prints 0 to 9 each on new line */
|
||||||
writeln("range iter test");
|
writeln("range iter test");
|
||||||
for (int i: range(10))
|
for (int i: range(10))
|
||||||
writeln(i);
|
writeln(i);
|
||||||
|
|
||||||
/* algorithm: map */
|
/* algorithm: map - prints 0.5 to 9.5 each on new line */
|
||||||
writeln("range map test");
|
writeln("range map test");
|
||||||
for (float f: map(range(10), [](int v) { return v + 0.5f; }))
|
for (float f: map(range(10), [](int v) { return v + 0.5f; }))
|
||||||
writeln(f);
|
writeln(f);
|
||||||
|
|
||||||
/* alrogithm: filter */
|
/* algorithm: filter - prints 10, 15, 8 each on new line */
|
||||||
writeln("range filter test");
|
writeln("range filter test");
|
||||||
auto il = { 5, 5, 5, 5, 5, 10, 15, 4, 8, 2 };
|
auto il = { 5, 5, 5, 5, 5, 10, 15, 4, 8, 2 };
|
||||||
for (int i: filter(iter(il), [](int v) { return v > 5; }))
|
for (int i: filter(iter(il), [](int v) { return v > 5; }))
|
||||||
writeln(i);
|
writeln(i);
|
||||||
|
|
||||||
/* generate string ABCDEF */
|
/* prints ABCDEF (ASCII 65, 66, 67, 68, 69, 70) */
|
||||||
String s(map(range(6), [](int v) -> char { return v + 65; }));
|
String s(map(range(6), [](int v) -> char { return v + 65; }));
|
||||||
writeln(s);
|
writeln(s);
|
||||||
|
|
||||||
|
/* join a few ranges together - prints 11, 22, 33 ... 99 each on new line */
|
||||||
|
auto x = { 11, 22, 33 };
|
||||||
|
auto y = { 44, 55, 66 };
|
||||||
|
auto z = { 77, 88, 99 };
|
||||||
|
for (auto i: join(iter(x), iter(y), iter(z))) {
|
||||||
|
writeln(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* chunk a range into subranges - prints
|
||||||
|
* {11, 22, 33}
|
||||||
|
* {44, 55, 66}
|
||||||
|
* {77, 88, 99}
|
||||||
|
*/
|
||||||
|
auto cr = { 11, 22, 33, 44, 55, 66, 77, 88, 99 };
|
||||||
|
for (auto r: chunks(iter(cr), 3))
|
||||||
|
writeln(r);
|
||||||
}
|
}
|
||||||
|
|
125
ostd/range.hh
125
ostd/range.hh
|
@ -13,6 +13,7 @@
|
||||||
#include "ostd/types.hh"
|
#include "ostd/types.hh"
|
||||||
#include "ostd/utility.hh"
|
#include "ostd/utility.hh"
|
||||||
#include "ostd/type_traits.hh"
|
#include "ostd/type_traits.hh"
|
||||||
|
#include "ostd/tuple.hh"
|
||||||
|
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
|
|
||||||
|
@ -1215,6 +1216,130 @@ ChunksRange<T> chunks(const T &it, RangeSize<T> chs) {
|
||||||
return ChunksRange<T>(it, chs);
|
return ChunksRange<T>(it, chs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template<Size I, Size N>
|
||||||
|
struct TupleEmptyRanges {
|
||||||
|
template<typename T>
|
||||||
|
static bool empty(const T &tup) {
|
||||||
|
if (!ostd::get<I>(tup).empty())
|
||||||
|
return false;
|
||||||
|
return TupleEmptyRanges<I + 1, N>::empty(tup);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<Size N>
|
||||||
|
struct TupleEmptyRanges<N, N> {
|
||||||
|
template<typename T>
|
||||||
|
static bool empty(const T &) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<Size I, Size N>
|
||||||
|
struct TupleEqualRanges {
|
||||||
|
template<typename T>
|
||||||
|
static bool equal(const T &tup1, const T &tup2) {
|
||||||
|
if (!ostd::get<I>(tup1).equals_front(ostd::get<I>(tup2)))
|
||||||
|
return false;
|
||||||
|
return TupleEqualRanges<I + 1, N>::empty(tup1, tup2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<Size N>
|
||||||
|
struct TupleEqualRanges<N, N> {
|
||||||
|
template<typename T>
|
||||||
|
static bool equal(const T &, const T &) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<Size I, Size N>
|
||||||
|
struct TuplePopRanges {
|
||||||
|
template<typename T>
|
||||||
|
static bool pop(T &tup) {
|
||||||
|
if (!ostd::get<I>(tup).empty()) {
|
||||||
|
return ostd::get<I>(tup).pop_front();
|
||||||
|
}
|
||||||
|
return TuplePopRanges<I + 1, N>::pop(tup);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<Size N>
|
||||||
|
struct TuplePopRanges<N, N> {
|
||||||
|
template<typename T>
|
||||||
|
static bool pop(T &) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<Size I, Size N, typename T>
|
||||||
|
struct TupleRangeFront {
|
||||||
|
template<typename U>
|
||||||
|
static T front(const U &tup) {
|
||||||
|
if (!ostd::get<I>(tup).empty()) {
|
||||||
|
return ostd::get<I>(tup).front();
|
||||||
|
}
|
||||||
|
return TupleRangeFront<I + 1, N, T>::front(tup);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<Size N, typename T>
|
||||||
|
struct TupleRangeFront<N, N, T> {
|
||||||
|
template<typename U>
|
||||||
|
static T front(const U &tup) {
|
||||||
|
return ostd::get<0>(tup).front();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ...R>
|
||||||
|
struct JoinRange: InputRange<JoinRange<R...>,
|
||||||
|
CommonType<ForwardRangeTag, RangeCategory<R>...>,
|
||||||
|
CommonType<RangeValue<R>...>, CommonType<RangeReference<R>...>,
|
||||||
|
CommonType<RangeSize<R>...>, CommonType<RangeDifference<R>...>> {
|
||||||
|
private:
|
||||||
|
Tuple<R...> p_ranges;
|
||||||
|
public:
|
||||||
|
JoinRange() = delete;
|
||||||
|
JoinRange(const R &...ranges): p_ranges(ranges...) {}
|
||||||
|
JoinRange(R &&...ranges): p_ranges(forward<R>(ranges)...) {}
|
||||||
|
JoinRange(const JoinRange &v): p_ranges(v.p_ranges) {}
|
||||||
|
JoinRange(JoinRange &&v): p_ranges(move(v.p_ranges)) {}
|
||||||
|
|
||||||
|
JoinRange &operator=(const JoinRange &v) {
|
||||||
|
p_ranges = v.p_ranges;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
JoinRange &operator=(JoinRange &&v) {
|
||||||
|
p_ranges = move(v.p_ranges);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const {
|
||||||
|
return detail::TupleEmptyRanges<0, sizeof...(R)>::empty(p_ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool equals_front(const JoinRange &r) const {
|
||||||
|
return detail::TupleEqualRanges<0, sizeof...(R)>::equal(p_ranges,
|
||||||
|
r.p_ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pop_front() {
|
||||||
|
return detail::TuplePopRanges<0, sizeof...(R)>::pop(p_ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonType<RangeReference<R>...> front() const {
|
||||||
|
return detail::TupleRangeFront<0, sizeof...(R),
|
||||||
|
CommonType<RangeReference<R>...>>::front(p_ranges);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename R1, typename R2, typename ...R>
|
||||||
|
JoinRange<R1, R2, R...> join(R1 r1, R2 r2, R ...rr) {
|
||||||
|
return JoinRange<R1, R2, R...>(move(r1), move(r2), move(rr)...);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct AppenderRange: OutputRange<AppenderRange<T>, typename T::Value,
|
struct AppenderRange: OutputRange<AppenderRange<T>, typename T::Value,
|
||||||
typename T::Reference, typename T::Size, typename T::Difference> {
|
typename T::Reference, typename T::Size, typename T::Difference> {
|
||||||
|
|
|
@ -1095,8 +1095,8 @@ namespace detail {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename U, typename ...V>
|
template<typename ...A>
|
||||||
using CommonType = typename detail::CommonTypeBase<T, U, V...>::Type;
|
using CommonType = typename detail::CommonTypeBase<A...>::Type;
|
||||||
|
|
||||||
/* aligned storage */
|
/* aligned storage */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue