#pragma once #include #include #include namespace geode::utils::ranges { template concept ValidConstContainer = requires(C const& c) { c.begin(); c.end(); typename C::value_type; }; template concept ValidMutContainer = requires(C& c) { c.begin(); c.end(); typename C::value_type; }; template concept ValidContainer = ValidConstContainer && ValidMutContainer; template concept ValidCUnaryPredicate = requires(P p, typename C::value_type const& t) { { p(t) } -> std::convertible_to; }; template concept ValidIntoConverter = requires(P p, From const& t) { { p(t) } -> std::convertible_to; }; template bool contains(C const& cont, typename C::value_type const& elem) { return std::find(cont.begin(), cont.end(), elem) != cont.end(); } template Predicate> bool contains(C const& cont, Predicate fun) { return std::find_if(cont.begin(), cont.end(), fun) != cont.end(); } template requires std::is_default_constructible_v && std::is_convertible_v Output join(C const& cont, Output const& separator) { auto res = Output(); bool first = true; for (auto& p : cont) { if (!first) { res += separator; } else { first = false; } res += p; } return res; } template std::string join(C const& cont, std::string const& separator) { auto res = std::string(); bool first = true; for (auto& p : cont) { if (!first) { res += separator; } else { first = false; } res += p; } return res; } template< ValidConstContainer C, class Output, ValidIntoConverter Conv > requires std::is_default_constructible_v Output join(C const& cont, Output const& separator, Conv converter) { auto res = Output(); bool first = true; for (auto& p : cont) { if (!first) { res += separator; } else { first = false; } res += Conv(p); } return res; } template C& push(C& container, C const& toAdd) { container.insert(container.end(), toAdd.begin(), toAdd.end()); return container; } template C& remove(C& container, typename C::value_type const& value) { container.erase( std::remove(container.begin(), container.end(), value), container.end() ); return container; } template Predicate> C filter(C const& container, Predicate filterFun) { auto res = C(); std::copy_if(container.begin(), container.end(), res.end(), filterFun); return res; } template requires requires(Reducer r, R& acc, typename C::value_type t) { { r(acc, t) } -> std::same_as; } R reduce(C const& container, Reducer reducer) { auto res = R(); for (auto& item : container) { reducer(res, item); } return res; } template< ValidConstContainer From, ValidContainer Into, ValidIntoConverter Mapper > Into map(From const& from, Mapper mapper) { auto res = Into(); std::transform(from.begin(), from.end(), res.end(), mapper); return res; } }