#pragma once #include #include #include #include #include #include namespace Swan { // Inherit from this class to make a class non-copyable class NonCopyable { public: NonCopyable(const NonCopyable &) = delete; NonCopyable(NonCopyable &&) noexcept = default; NonCopyable &operator=(const NonCopyable &) = delete; NonCopyable &operator=(NonCopyable &&) = default; protected: NonCopyable() = default; ~NonCopyable() = default; }; // Take a deleter function, turn it into a class with an operator() for unique_ptr template class CPtrDeleter { public: void operator()(T *ptr) { Func(ptr); } }; // This is just a bit nicer to use than using unique_ptr directly template using CPtr = std::unique_ptr>; // Take a function, run it when the object goes out of scope template class Deferred: NonCopyable { public: Deferred() = default; ~Deferred() { Func(); } }; // Calling begin/end is stupid... template auto callBegin(T &v) { using namespace std; return begin(v); } template auto callEnd(T &v) { using namespace std; return end(v); } // Ret can't be a reference, because C++ doesn't support optional. template()>> class Iter { public: class It { public: It(std::optional next, Func &func): next_(std::move(next)), func_(func) {} bool operator==(const It &other) const { return next_ == std::nullopt && other.next_ == std::nullopt; } bool operator!=(const It &other) const { return !(*this == other); } void operator++() { auto val(func_()); if (val) next_.emplace(std::move(*val)); else next_.reset(); } Ret operator*() { return std::move(*next_); } private: std::optional next_; Func &func_; }; Iter(Func func): func_(func) {} operator Iter()>>() { return Iter()>>(func_); } It begin() { return It(func_(), func_); } It end() { return It(std::nullopt, func_); } private: Func func_; }; template auto map(InputIterator first, InputIterator last, Func func) { using RetT = decltype(func(*first)); auto l = [=]() mutable -> std::optional { if (first == last) return std::nullopt; RetT r = func(*first); ++first; return r; }; return Iter(l); } template auto map(Range &rng, Func func) { return map(callBegin(rng), callEnd(rng), func); } template auto filter(InputIterator first, InputIterator last, Func pred) { using RetT = std::remove_reference_t; auto l = [=]() mutable -> std::optional { if (first == last) return std::nullopt; while (!pred(*first)) { ++first; if (first == last) return std::nullopt; } RetT r = *first; ++first; return r; }; return Iter(l); } template auto filter(Range &rng, Func func) { return filter(callBegin(rng), callEnd(rng), func); } template auto mapFilter(InputIterator first, InputIterator last, Func func) { using RetT = std::remove_reference_t; auto l = [=]() mutable -> std::optional { if (first == last) return std::nullopt; std::optional r; while ((r = func(*first)) == std::nullopt) { ++first; if (first == last) return std::nullopt; } ++first; return r; }; return Iter(l); } template auto mapFilter(Range &rng, Func func) { return mapFilter(callBegin(rng), callEnd(rng), func); } }