83 lines
2.1 KiB
C++
83 lines
2.1 KiB
C++
#pragma once
|
|
|
|
#include "../concepts/container.hpp"
|
|
#include <algorithm>
|
|
#include <ranges>
|
|
#include <unordered_set>
|
|
#include <vector>
|
|
|
|
|
|
namespace util {
|
|
namespace rg = std::ranges;
|
|
namespace detail {
|
|
template <typename Collection, rg::input_range R>
|
|
constexpr auto collect_range(R &&r) -> Collection {
|
|
Collection c;
|
|
if constexpr (rg::sized_range<R> && util::reservable<Collection>) {
|
|
c.reserve(r.size());
|
|
}
|
|
|
|
if constexpr (util::back_insertible<Collection>) {
|
|
rg::move(r, std::back_inserter(c));
|
|
} else if constexpr (util::back_emplaceable<Collection,
|
|
decltype(*r.begin())>) {
|
|
for (auto &&e : r) {
|
|
c.emplace_back(std::move(e));
|
|
}
|
|
} else if constexpr (util::emplaceable<Collection, decltype(*r.begin())>) {
|
|
for (auto &&e : r) {
|
|
c.emplace(std::move(e));
|
|
}
|
|
}
|
|
|
|
return c;
|
|
}
|
|
|
|
template <typename Collection> struct collect_range_adaptor {
|
|
template <rg::input_range R> constexpr auto operator()(R &&r) const {
|
|
return collect_range<Collection>(std::forward<R>(r));
|
|
}
|
|
};
|
|
|
|
template <typename Collection, rg::viewable_range R>
|
|
constexpr auto operator|(R &&r,
|
|
const collect_range_adaptor<Collection> &adaptor) {
|
|
return adaptor(std::forward<R>(r));
|
|
}
|
|
} // namespace detail
|
|
|
|
namespace views {
|
|
|
|
template <typename Collection>
|
|
inline detail::collect_range_adaptor<Collection> collect;
|
|
}
|
|
|
|
template <typename Collection, rg::range R>
|
|
|
|
constexpr auto collect(R &&r) -> Collection {
|
|
return r | views::collect<Collection>;
|
|
}
|
|
|
|
template <typename Range>
|
|
constexpr auto to_vector(Range r)
|
|
-> std::vector<rg::range_value_t<decltype(r)>> {
|
|
std::vector<rg::range_value_t<decltype(r)>> v;
|
|
|
|
if constexpr (rg::sized_range<decltype(r)>) {
|
|
v.reserve(rg::size(r));
|
|
}
|
|
|
|
std::ranges::copy(r, std::back_inserter(v));
|
|
|
|
return v;
|
|
}
|
|
|
|
template <typename Range>
|
|
constexpr auto to_unordered_set(Range r)
|
|
-> std::unordered_set<std::ranges::range_value_t<decltype(r)>> {
|
|
std::unordered_set<std::ranges::range_value_t<decltype(r)>> v(r.begin(),
|
|
r.end());
|
|
return v;
|
|
}
|
|
|
|
} // namespace util
|