clean up join/zip ranges with c++17 fold expressions

master
Daniel Kolesa 2017-02-10 20:26:13 +01:00
parent d06637eac6
commit 2e773b3849
2 changed files with 26 additions and 110 deletions

View File

@ -8,10 +8,6 @@ make the language easier and more convenient to use.
Documentation for OctaSTD can be found at https://wiki.octaforge.org/docs/octastd. Documentation for OctaSTD can be found at https://wiki.octaforge.org/docs/octastd.
It's not necessary that your compiler fully supports C++17, only C++14
language is used, but new C++17 containers have to be present, such as
`string_view` and `optional`.
## Supported compilers ## Supported compilers
Compiler | Version Compiler | Version
@ -35,12 +31,10 @@ use GCC/Clang, if you need Visual Studio, LLVM integration exists.
Sadly, it's not possible to properly integrate `std::string` and `std::hash` Sadly, it's not possible to properly integrate `std::string` and `std::hash`
with OctaSTD ranges without utilizing `std::string_view`. Also, C++17 provides with OctaSTD ranges without utilizing `std::string_view`. Also, C++17 provides
library features that OctaSTD would have to implement otherwise, which would library features that OctaSTD would have to implement otherwise, which would
lead to potentially incompatible APIs. However, OctaSTD does not make wide lead to potentially incompatible APIs. C++17 also provides some nice language
use of C++17 language features, limiting itself mostly to library features features (such as `if constexpr` and fold epxressions) which allow a lot of
which have been present for more or less a pretty long time (in experimental code to be written in a cleaner way. However, it is made sure that no features
namespace for example) which should avoid buggy behavior. There is still the beyond the minimum supported compiler are necessary to use the library.
problem of requiring a very recent toolchain, but this situation should solve
itself in near future.
## Supported operating systems ## Supported operating systems

View File

@ -1485,44 +1485,6 @@ public:
}; };
namespace detail { namespace detail {
template<size_t I, size_t N>
struct JoinRangeEmpty {
template<typename T>
static bool empty(T const &tup) {
if (!std::get<I>(tup).empty()) {
return false;
}
return JoinRangeEmpty<I + 1, N>::empty(tup);
}
};
template<size_t N>
struct JoinRangeEmpty<N, N> {
template<typename T>
static bool empty(T const &) {
return true;
}
};
template<size_t I, size_t N>
struct TupleRangeEqual {
template<typename T>
static bool equal(T const &tup1, T const &tup2) {
if (!std::get<I>(tup1).equals_front(std::get<I>(tup2))) {
return false;
}
return TupleRangeEqual<I + 1, N>::equal(tup1, tup2);
}
};
template<size_t N>
struct TupleRangeEqual<N, N> {
template<typename T>
static bool equal(T const &, T const &) {
return true;
}
};
template<size_t I, size_t N> template<size_t I, size_t N>
struct JoinRangePop { struct JoinRangePop {
template<typename T> template<typename T>
@ -1587,13 +1549,17 @@ public:
} }
bool empty() const { bool empty() const {
return detail::JoinRangeEmpty<0, sizeof...(R)>::empty(p_ranges); return std::apply([](auto const &...args) {
return (... && args.empty());
}, p_ranges);
} }
bool equals_front(JoinRange const &r) const { bool equals_front(JoinRange const &r) const {
return detail::TupleRangeEqual<0, sizeof...(R)>::equal( return std::apply([&r](auto const &...r1) {
p_ranges, r.p_ranges return std::apply([&](auto const &...r2) {
); return (... && r1.equals_front(r2));
}, r);
}, p_ranges);
} }
bool pop_front() { bool pop_front() {
@ -1620,58 +1586,6 @@ namespace detail {
template<typename ...T> template<typename ...T>
using ZipValue = typename detail::ZipValueType<T...>::Type; using ZipValue = typename detail::ZipValueType<T...>::Type;
template<size_t I, size_t N>
struct ZipRangeEmpty {
template<typename T>
static bool empty(T const &tup) {
if (std::get<I>(tup).empty()) {
return true;
}
return ZipRangeEmpty<I + 1, N>::empty(tup);
}
};
template<size_t N>
struct ZipRangeEmpty<N, N> {
template<typename T>
static bool empty(T const &) {
return false;
}
};
template<size_t I, size_t N>
struct ZipRangePop {
template<typename T>
static bool pop(T &tup) {
return (
std::get<I>(tup).pop_front() && ZipRangePop<I + 1, N>::pop(tup)
);
}
};
template<size_t N>
struct ZipRangePop<N, N> {
template<typename T>
static bool pop(T &) {
return true;
}
};
template<typename ...T>
struct ZipRangeFront {
template<typename U, size_t ...I>
static ZipValue<T...> tup_get(U const &tup, std::index_sequence<I...>) {
return ZipValue<T...>(std::get<I>(tup).front()...);
}
template<typename U>
static ZipValue<T...> front(U const &tup) {
return ZipRangeFront<T...>::tup_get(
tup, std::make_index_sequence<sizeof...(T)>()
);
}
};
} }
template<typename ...R> template<typename ...R>
@ -1701,21 +1615,29 @@ public:
} }
bool empty() const { bool empty() const {
return detail::ZipRangeEmpty<0, sizeof...(R)>::empty(p_ranges); return std::apply([](auto const &...args) {
return (... || args.empty());
}, p_ranges);
} }
bool equals_front(ZipRange const &r) const { bool equals_front(ZipRange const &r) const {
return detail::TupleRangeEqual<0, sizeof...(R)>::equal( return std::apply([&r](auto const &...r1) {
p_ranges, r.p_ranges return std::apply([&](auto const &...r2) {
); return (... && r1.equals_front(r2));
}, r);
}, p_ranges);
} }
bool pop_front() { bool pop_front() {
return detail::ZipRangePop<0, sizeof...(R)>::pop(p_ranges); return std::apply([](auto &...args) {
return (... && args.pop_front());
}, p_ranges);
} }
detail::ZipValue<RangeReference<R>...> front() const { detail::ZipValue<RangeReference<R>...> front() const {
return detail::ZipRangeFront<RangeReference<R>...>::front(p_ranges); return std::apply([](auto &&...args) {
return detail::ZipValue<RangeReference<R>...>{args.front()...};
}, p_ranges);
} }
}; };