|
|
@@ -7,74 +7,58 @@
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
-#include <optional>
|
|
|
+#include <stream/forward.h>
|
|
|
|
|
|
#include <stream/detail/identity.h>
|
|
|
+#include <stream/detail/invoke.h>
|
|
|
#include <stream/detail/named_pair.h>
|
|
|
#include <stream/detail/traits.h>
|
|
|
|
|
|
-#define FWD(x) std::forward<decltype(x)>(x)
|
|
|
-
|
|
|
-namespace stream::detail {
|
|
|
-template <typename T, typename Comp, typename Proj>
|
|
|
-bool compare(T const & l, T const & r, Comp && comp, Proj && proj) {
|
|
|
- return std::invoke(FWD(comp), std::invoke(proj, l), std::invoke(proj, r));
|
|
|
-}
|
|
|
-}
|
|
|
+#include <stream/detail/macro.h>
|
|
|
|
|
|
namespace stream::ranges {
|
|
|
-
|
|
|
-template <typename It, typename S, typename Comp = std::less<>,
|
|
|
- typename Proj = detail::identity,
|
|
|
- typename = std::enable_if_t<detail::is_comparable_v<It, S>>>
|
|
|
-auto minmax(It it, S end, Comp comp = {}, Proj proj = {}) {
|
|
|
- detail::min_max_result v(*it, *it);
|
|
|
- for (++it; it != end; ++it) {
|
|
|
- if (detail::compare(v.max, *it, comp, proj)) { v.max = *it; }
|
|
|
- if (detail::compare(*it, v.min, comp, proj)) { v.min = *it; }
|
|
|
- }
|
|
|
- return v;
|
|
|
-}
|
|
|
-
|
|
|
-template <typename Stream, typename Comp = std::less<>,
|
|
|
+template <typename T, typename Comp = std::less<>,
|
|
|
typename Proj = detail::identity>
|
|
|
-auto minmax(Stream const & stream, Comp comp = {}, Proj proj = {}) {
|
|
|
- return minmax(stream.begin(), stream.end(), std::move(comp), std::move(proj));
|
|
|
+auto minmax(T const & l, T const & r, Comp comp = {}, Proj proj = {})
|
|
|
+ -> detail::min_max_result<T const &, T const &> {
|
|
|
+ if (detail::invoke(comp, l, r, proj, proj)) { return {l, r}; }
|
|
|
+ return {r, l};
|
|
|
}
|
|
|
|
|
|
template <typename It, typename S, typename Comp = std::less<>,
|
|
|
typename Proj = detail::identity,
|
|
|
- typename = std::enable_if_t<detail::is_comparable_v<It, S>>>
|
|
|
-auto min(It it, S end, Comp comp = {}, Proj proj = {}) {
|
|
|
- auto v = *it;
|
|
|
+ REQUIRES((detail::is_comparable_v<It, S>))>
|
|
|
+auto minmax_element(It it, S end, Comp comp = {}, Proj proj = {}) {
|
|
|
+ detail::min_max_result rval(it, it);
|
|
|
for (++it; it != end; ++it) {
|
|
|
- if (detail::compare(*it, v, comp, proj)) { v = *it; }
|
|
|
+ if (detail::invoke(comp, it, rval.min, proj, proj)) {
|
|
|
+ rval.min = it;
|
|
|
+ } else if (detail::invoke(comp, rval.max, it, proj, proj)) {
|
|
|
+ rval.max = it;
|
|
|
+ }
|
|
|
}
|
|
|
- return v;
|
|
|
+ return rval;
|
|
|
}
|
|
|
|
|
|
template <typename Stream, typename Comp = std::less<>,
|
|
|
typename Proj = detail::identity>
|
|
|
-auto min(Stream const & stream, Comp comp = {}, Proj proj = {}) {
|
|
|
- return min(stream.begin(), stream.end(), std::move(comp), std::move(proj));
|
|
|
+auto minmax_element(Stream const & stream, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return minmax_element(stream.begin(), stream.end(), comp, proj);
|
|
|
}
|
|
|
|
|
|
-template <typename It, typename S, typename Comp = std::less<>,
|
|
|
- typename Proj = detail::identity,
|
|
|
- typename = std::enable_if_t<detail::is_comparable_v<It, S>>>
|
|
|
-auto max(It it, S end, Comp comp = {}, Proj proj = {}) {
|
|
|
- auto v = *it;
|
|
|
- for (++it; it != end; ++it) {
|
|
|
- if (detail::compare(v, *it, comp, proj)) { v = *it; }
|
|
|
- }
|
|
|
- return v;
|
|
|
+template <typename T, typename Comp = std::less<>,
|
|
|
+ typename Proj = detail::identity>
|
|
|
+auto minmax(std::initializer_list<T> stream, Comp comp = {}, Proj proj = {}) {
|
|
|
+ auto result = minmax_element(stream.begin(), stream.end(), comp, proj);
|
|
|
+ return detail::min_max_result(*result.min, *result.max);
|
|
|
}
|
|
|
|
|
|
template <typename Stream, typename Comp = std::less<>,
|
|
|
typename Proj = detail::identity>
|
|
|
-auto max(Stream const & stream, Comp comp = {}, Proj proj = {}) {
|
|
|
- return max(stream.begin(), stream.end(), std::move(comp), std::move(proj));
|
|
|
+auto minmax(Stream const & stream, Comp comp = {}, Proj proj = {}) {
|
|
|
+ auto result = minmax_element(stream.begin(), stream.end(), comp, proj);
|
|
|
+ return detail::min_max_result(*result.min, *result.max);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#undef FWD
|
|
|
+#include <stream/detail/undef.h>
|