implement zip and tuple ToString
parent
f651940570
commit
6c840ad830
|
@ -29,9 +29,8 @@ int main() {
|
|||
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))) {
|
||||
for (auto i: join(iter(x), iter(y), iter(z)))
|
||||
writeln(i);
|
||||
}
|
||||
|
||||
/* chunk a range into subranges - prints
|
||||
* {11, 22, 33}
|
||||
|
@ -41,4 +40,12 @@ int main() {
|
|||
auto cr = { 11, 22, 33, 44, 55, 66, 77, 88, 99 };
|
||||
for (auto r: chunks(iter(cr), 3))
|
||||
writeln(r);
|
||||
|
||||
/* {11, 44, 77}, {22, 55, 88}, {33, 66, 99} */
|
||||
for (auto v: zip(iter(x), iter(y), iter(z)))
|
||||
writeln(v);
|
||||
|
||||
/* 2-tuple zip uses Pair */
|
||||
for (auto v: zip(iter({ 5, 10, 15, 20 }), iter({ 6, 11, 16, 21 })))
|
||||
writeln(v.first, ", ", v.second);
|
||||
}
|
||||
|
|
144
ostd/range.hh
144
ostd/range.hh
|
@ -1218,17 +1218,17 @@ ChunksRange<T> chunks(const T &it, RangeSize<T> chs) {
|
|||
|
||||
namespace detail {
|
||||
template<Size I, Size N>
|
||||
struct TupleEmptyRanges {
|
||||
struct JoinRangeEmpty {
|
||||
template<typename T>
|
||||
static bool empty(const T &tup) {
|
||||
if (!ostd::get<I>(tup).empty())
|
||||
return false;
|
||||
return TupleEmptyRanges<I + 1, N>::empty(tup);
|
||||
return JoinRangeEmpty<I + 1, N>::empty(tup);
|
||||
}
|
||||
};
|
||||
|
||||
template<Size N>
|
||||
struct TupleEmptyRanges<N, N> {
|
||||
struct JoinRangeEmpty<N, N> {
|
||||
template<typename T>
|
||||
static bool empty(const T &) {
|
||||
return true;
|
||||
|
@ -1236,17 +1236,17 @@ namespace detail {
|
|||
};
|
||||
|
||||
template<Size I, Size N>
|
||||
struct TupleEqualRanges {
|
||||
struct TupleRangeEqual {
|
||||
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);
|
||||
return TupleRangeEqual<I + 1, N>::equal(tup1, tup2);
|
||||
}
|
||||
};
|
||||
|
||||
template<Size N>
|
||||
struct TupleEqualRanges<N, N> {
|
||||
struct TupleRangeEqual<N, N> {
|
||||
template<typename T>
|
||||
static bool equal(const T &, const T &) {
|
||||
return true;
|
||||
|
@ -1254,18 +1254,18 @@ namespace detail {
|
|||
};
|
||||
|
||||
template<Size I, Size N>
|
||||
struct TuplePopRanges {
|
||||
struct JoinRangePop {
|
||||
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);
|
||||
return JoinRangePop<I + 1, N>::pop(tup);
|
||||
}
|
||||
};
|
||||
|
||||
template<Size N>
|
||||
struct TuplePopRanges<N, N> {
|
||||
struct JoinRangePop<N, N> {
|
||||
template<typename T>
|
||||
static bool pop(T &) {
|
||||
return false;
|
||||
|
@ -1273,18 +1273,18 @@ namespace detail {
|
|||
};
|
||||
|
||||
template<Size I, Size N, typename T>
|
||||
struct TupleRangeFront {
|
||||
struct JoinRangeFront {
|
||||
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);
|
||||
return JoinRangeFront<I + 1, N, T>::front(tup);
|
||||
}
|
||||
};
|
||||
|
||||
template<Size N, typename T>
|
||||
struct TupleRangeFront<N, N, T> {
|
||||
struct JoinRangeFront<N, N, T> {
|
||||
template<typename U>
|
||||
static T front(const U &tup) {
|
||||
return ostd::get<0>(tup).front();
|
||||
|
@ -1317,20 +1317,20 @@ public:
|
|||
}
|
||||
|
||||
bool empty() const {
|
||||
return detail::TupleEmptyRanges<0, sizeof...(R)>::empty(p_ranges);
|
||||
return detail::JoinRangeEmpty<0, sizeof...(R)>::empty(p_ranges);
|
||||
}
|
||||
|
||||
bool equals_front(const JoinRange &r) const {
|
||||
return detail::TupleEqualRanges<0, sizeof...(R)>::equal(p_ranges,
|
||||
return detail::TupleRangeEqual<0, sizeof...(R)>::equal(p_ranges,
|
||||
r.p_ranges);
|
||||
}
|
||||
|
||||
bool pop_front() {
|
||||
return detail::TuplePopRanges<0, sizeof...(R)>::pop(p_ranges);
|
||||
return detail::JoinRangePop<0, sizeof...(R)>::pop(p_ranges);
|
||||
}
|
||||
|
||||
CommonType<RangeReference<R>...> front() const {
|
||||
return detail::TupleRangeFront<0, sizeof...(R),
|
||||
return detail::JoinRangeFront<0, sizeof...(R),
|
||||
CommonType<RangeReference<R>...>>::front(p_ranges);
|
||||
}
|
||||
};
|
||||
|
@ -1340,6 +1340,118 @@ JoinRange<R1, R2, R...> join(R1 r1, R2 r2, R ...rr) {
|
|||
return JoinRange<R1, R2, R...>(move(r1), move(r2), move(rr)...);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template<typename ...T>
|
||||
struct ZipValueType {
|
||||
using Type = Tuple<T...>;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct ZipValueType<T, U> {
|
||||
using Type = Pair<T, U>;
|
||||
};
|
||||
|
||||
template<typename ...T>
|
||||
using ZipValue = typename detail::ZipValueType<T...>::Type;
|
||||
|
||||
template<Size I, Size N>
|
||||
struct ZipRangeEmpty {
|
||||
template<typename T>
|
||||
static bool empty(const T &tup) {
|
||||
if (ostd::get<I>(tup).empty())
|
||||
return true;
|
||||
return ZipRangeEmpty<I + 1, N>::empty(tup);
|
||||
}
|
||||
};
|
||||
|
||||
template<Size N>
|
||||
struct ZipRangeEmpty<N, N> {
|
||||
template<typename T>
|
||||
static bool empty(const T &) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template<Size I, Size N>
|
||||
struct ZipRangePop {
|
||||
template<typename T>
|
||||
static bool pop(T &tup) {
|
||||
return ostd::get<I>(tup).pop_front() &&
|
||||
ZipRangePop<I + 1, N>::pop(tup);
|
||||
}
|
||||
};
|
||||
|
||||
template<Size N>
|
||||
struct ZipRangePop<N, N> {
|
||||
template<typename T>
|
||||
static bool pop(T &) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ...T>
|
||||
struct ZipRangeFront {
|
||||
template<typename U, Size ...I>
|
||||
static ZipValue<T...> tup_get(const U &tup, detail::TupleIndices<I...>) {
|
||||
return ZipValue<T...>(ostd::get<I>(tup).front()...);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
static ZipValue<T...> front(const U &tup) {
|
||||
using Index = detail::MakeTupleIndices<sizeof...(T)>;
|
||||
return ZipRangeFront<T...>::tup_get(tup, Index());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename ...R>
|
||||
struct ZipRange: InputRange<ZipRange<R...>,
|
||||
CommonType<ForwardRangeTag, RangeCategory<R>...>,
|
||||
detail::ZipValue<RangeReference<R>...>,
|
||||
detail::ZipValue<RangeReference<R>...>,
|
||||
CommonType<RangeSize<R>...>, CommonType<RangeDifference<R>...>> {
|
||||
private:
|
||||
Tuple<R...> p_ranges;
|
||||
public:
|
||||
ZipRange() = delete;
|
||||
ZipRange(const R &...ranges): p_ranges(ranges...) {}
|
||||
ZipRange(R &&...ranges): p_ranges(forward<R>(ranges)...) {}
|
||||
ZipRange(const ZipRange &v): p_ranges(v.p_ranges) {}
|
||||
ZipRange(ZipRange &&v): p_ranges(move(v.p_ranges)) {}
|
||||
|
||||
ZipRange &operator=(const ZipRange &v) {
|
||||
p_ranges = v.p_ranges;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZipRange &operator=(ZipRange &&v) {
|
||||
p_ranges = move(v.p_ranges);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return detail::ZipRangeEmpty<0, sizeof...(R)>::empty(p_ranges);
|
||||
}
|
||||
|
||||
bool equals_front(const ZipRange &r) const {
|
||||
return detail::TupleRangeEqual<0, sizeof...(R)>::equal(p_ranges,
|
||||
r.p_ranges);
|
||||
}
|
||||
|
||||
bool pop_front() {
|
||||
return detail::ZipRangePop<0, sizeof...(R)>::pop(p_ranges);
|
||||
}
|
||||
|
||||
detail::ZipValue<RangeReference<R>...> front() const {
|
||||
return detail::ZipRangeFront<RangeReference<R>...>::front(p_ranges);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename R1, typename R2, typename ...R>
|
||||
ZipRange<R1, R2, R...> zip(R1 r1, R2 r2, R ...rr) {
|
||||
return ZipRange<R1, R2, R...>(move(r1), move(r2), move(rr)...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct AppenderRange: OutputRange<AppenderRange<T>, typename T::Value,
|
||||
typename T::Reference, typename T::Size, typename T::Difference> {
|
||||
|
|
|
@ -850,9 +850,49 @@ template<typename T, typename U> struct ToString<Pair<T, U>> {
|
|||
using Result = String;
|
||||
String operator()(const Argument &v) {
|
||||
String ret("{");
|
||||
ret += ToString<RemoveReference<RemoveCv<T>>>()(v.first);
|
||||
ret += ToString<RemoveCv<RemoveReference<T>>>()(v.first);
|
||||
ret += ", ";
|
||||
ret += ToString<RemoveReference<RemoveCv<U>>>()(v.second);
|
||||
ret += ToString<RemoveCv<RemoveReference<U>>>()(v.second);
|
||||
ret += "}";
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<Size I, Size N>
|
||||
struct TupleToString {
|
||||
template<typename T>
|
||||
static void append(String &ret, const T &tup) {
|
||||
ret += ", ";
|
||||
ret += ToString<RemoveCv<RemoveReference<
|
||||
decltype(ostd::get<I>(tup))>>>()(ostd::get<I>(tup));
|
||||
TupleToString<I + 1, N>::append(ret, tup);
|
||||
}
|
||||
};
|
||||
|
||||
template<Size N>
|
||||
struct TupleToString<N, N> {
|
||||
template<typename T>
|
||||
static void append(String &, const T &) {}
|
||||
};
|
||||
|
||||
template<Size N>
|
||||
struct TupleToString<0, N> {
|
||||
template<typename T>
|
||||
static void append(String &ret, const T &tup) {
|
||||
ret += ToString<RemoveCv<RemoveReference<
|
||||
decltype(ostd::get<0>(tup))>>>()(ostd::get<0>(tup));
|
||||
TupleToString<1, N>::append(ret, tup);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename ...T> struct ToString<Tuple<T...>> {
|
||||
using Argument = Tuple<T...>;
|
||||
using Result = String;
|
||||
String operator()(const Argument &v) {
|
||||
String ret("{");
|
||||
detail::TupleToString<0, sizeof...(T)>::append(ret, v);
|
||||
ret += "}";
|
||||
return ret;
|
||||
}
|
||||
|
@ -860,7 +900,7 @@ template<typename T, typename U> struct ToString<Pair<T, U>> {
|
|||
|
||||
template<typename T>
|
||||
typename ToString<T>::Result to_string(const T &v) {
|
||||
return ToString<RemoveReference<RemoveCv<T>>>()(v);
|
||||
return ToString<RemoveCv<RemoveReference<T>>>()(v);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
Loading…
Reference in New Issue