#pragma once #include #include #include #include #include #include #include #include namespace vcpkg::Util { template using ElementT = std::remove_reference_t::iterator>())>; namespace Vectors { template> void append(std::vector* augend, const Container& addend) { augend->insert(augend->end(), addend.begin(), addend.end()); } template bool contains(const Vec& container, const Key& item) { return std::find(container.begin(), container.end(), item) != container.end(); } } namespace Sets { template bool contains(const Container& container, const Key& item) { return container.find(item) != container.end(); } } namespace Maps { template void transform_values(const std::unordered_map& container, std::unordered_map& output, Func func) { std::for_each(container.cbegin(), container.cend(), [&](const std::pair& p) { output[p.first] = func(p.second); }); } } template> std::vector filter(const Range& xs, Pred&& f) { std::vector ret; for (auto&& x : xs) { if (f(x)) ret.push_back(x); } return ret; } template using FmapOut = std::remove_reference_t()(*std::declval().begin()))>; template> std::vector fmap(Range&& xs, Func&& f) { std::vector ret; ret.reserve(xs.size()); for (auto&& x : xs) ret.push_back(f(x)); return ret; } template using FmapFlattenOut = std::decay_t()(*begin(std::declval()))))>; template> std::vector fmap_flatten(Cont&& xs, Func&& f) { std::vector ret; for (auto&& x : xs) for (auto&& y : f(x)) ret.push_back(std::move(y)); return ret; } template void erase_remove_if(Container& cont, Pred pred) { cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end()); } template auto find(Container&& cont, V&& v) { using std::begin; using std::end; return std::find(begin(cont), end(cont), v); } template auto find_if(Container&& cont, Pred pred) { using std::begin; using std::end; return std::find_if(begin(cont), end(cont), pred); } template auto find_if_not(Container&& cont, Pred pred) { using std::begin; using std::end; return std::find_if_not(begin(cont), end(cont), pred); } template void group_by(const Container& cont, std::map>* output, Func&& f) { for (const V& element : cont) { K key = f(element); (*output)[key].push_back(&element); } } template> void sort(Range& cont, Comp comp = Comp()) { using std::begin; using std::end; std::sort(begin(cont), end(cont), comp); } template bool any_of(Range&& rng, Pred pred) { return std::any_of(rng.begin(), rng.end(), std::move(pred)); } template Range&& sort_unique_erase(Range&& cont) { using std::begin; using std::end; std::sort(begin(cont), end(cont)); cont.erase(std::unique(begin(cont), end(cont)), end(cont)); return std::forward(cont); } template bool all_equal(const Range1& r1, const Range2& r2) { using std::begin; using std::end; return std::equal(begin(r1), end(r1), begin(r2), end(r2)); } template())->first)>> std::vector extract_keys(AssocContainer&& input_map) { return fmap(input_map, [](auto&& p) { return p.first; }); } struct MoveOnlyBase { MoveOnlyBase() = default; MoveOnlyBase(const MoveOnlyBase&) = delete; MoveOnlyBase(MoveOnlyBase&&) = default; MoveOnlyBase& operator=(const MoveOnlyBase&) = delete; MoveOnlyBase& operator=(MoveOnlyBase&&) = default; ~MoveOnlyBase() = default; }; struct ResourceBase { ResourceBase() = default; ResourceBase(const ResourceBase&) = delete; ResourceBase(ResourceBase&&) = delete; ResourceBase& operator=(const ResourceBase&) = delete; ResourceBase& operator=(ResourceBase&&) = delete; ~ResourceBase() = default; }; template struct LockGuardPtr; template struct LockGuarded { friend struct LockGuardPtr; LockGuardPtr lock() { return *this; } private: std::mutex m_mutex; T m_t; }; template struct LockGuardPtr { T& operator*() { return m_ptr; } T* operator->() { return &m_ptr; } T* get() { return &m_ptr; } LockGuardPtr(LockGuarded& sync) : m_lock(sync.m_mutex), m_ptr(sync.m_t) {} private: std::unique_lock m_lock; T& m_ptr; }; namespace Enum { template E to_enum(bool b) { return b ? E::YES : E::NO; } template bool to_bool(E e) { return e == E::YES; } } template void unused(const Ts&...) { } template T copy(const T& t) { return t; } }