commit fc8b9d0a4b645d8af8c447b80f5a2bc8ee4ce3d0 Author: Argon.Sun Date: Sat Jan 14 14:39:16 2023 +0800 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..26557a3 --- /dev/null +++ b/main.cpp @@ -0,0 +1,21 @@ +#include +#include + +#include "rusty.hpp" + +int main() { + rs::vector> v = {{10, 20, 25}, {30, 40, 55}, {60, 73, 80}}; + auto res = v.into_iter_ptr().flat_map([](const rs::vector* v)->auto{return v->into_iter();}) + // .partition>([](int x) -> auto { return x % 2 == 0; }); + // .skip_while([](int v)->bool { return v < 30; }) + .inspect([](int x) { std::cout << "check " << x << std::endl;}) + // .map([](int x)->float{ return x * 3.14159;}) + // .take_while([](float v)->bool { return v < 100; }) + // .enumerate() + // .collect>(); + .sum(); + std::cout << res << std::endl;; + rs::map mp = {{1, 4.0}, {2, 6.0}, {3, 6.6}}; + std::cout << mp.into_iter().map([](int a, float b)->float{ return a + b * b; }).sum() << std::endl; + return 0; +} diff --git a/rs_iter.hpp b/rs_iter.hpp new file mode 100644 index 0000000..7b3d7c8 --- /dev/null +++ b/rs_iter.hpp @@ -0,0 +1,500 @@ +#ifndef _RC_ITER_HPP_ +#define _RC_ITER_HPP_ + +#include +#include +#include +#include + +namespace rs { + +template +struct InvokeType { + template + auto Call(F f, ARGS... args) { return f(std::forward(args)...); } + template + void CallNoReturn(F f, ARGS... args) { f(std::forward(args)...); } + template + auto CallFold(F f, S s, ARGS... args) { return f(std::forward(s), std::forward(args)...); } +}; + +template +struct InvokeType> { + template + auto Call(F f, std::pair arg) { return f(arg.first, arg.second); } + template + void CallNoReturn(F f, std::pair arg) { f(arg.first, arg.second); } + template + auto CallFold(F f, S s, std::pair arg) { return f(std::forward(s), arg.first, arg.second); } +}; + +template +struct InvokeType> { + using sequence_type = std::index_sequence_for; + template + auto Call(F f, std::tuple arg) { return UnpackCall(std::forward(f), arg, sequence_type{}); } + template + void CallNoReturn(F f, std::tuple arg) { UnpackCallNoReturn(std::forward(f), arg, sequence_type{}); } + template + auto CallFold(F f, S s, std::tuple arg) { return UnpackCallFold(std::forward(f), std::forward(s), arg, sequence_type{}); } + + template + auto UnpackCall(F f, std::tuple& arg, std::index_sequence) { return f(std::get(arg)...); } + template + void UnpackCallNoReturn(F f, std::tuple& arg, std::index_sequence) { f(std::get(arg)...); } + template + auto UnpackCallFold(F f, S s, std::tuple& arg, std::index_sequence) { return f(s, std::get(arg)...); } +}; + +template +struct StdFuncType { + using type = void; + using return_type = void; +}; +template +struct StdFuncType { + using type = std::function; + using return_type = RET; +}; +template +struct StdFuncType { + using type = std::function; + using return_type = RET; +}; + +template +struct FunctionType { + using type = typename StdFuncType::type; + using return_type = typename StdFuncType::return_type; +}; +template +struct FunctionType { + using type = std::function; + using return_type = RET; +}; +template +struct FunctionType { + using type = std::function; + using return_type = RET; +}; + +template typename TP> +struct TemplateChecker { + static constexpr bool value = false; +}; +template typename TP, typename... ARGS> +struct TemplateChecker, TP> { + static constexpr bool value = true; +}; + +template +struct iterator { + using value_type = T; + + std::optional next() { + return iter(); + } + + size_t count() { + size_t result = 0; + for (auto n = next(); n.has_value(); n = next()) + result++; + return result; + } + + std::optional nth(size_t n) { + while (true) { + std::optional value = next(); + if (n-- == 0 || !value.has_value()) + return value; + } + } + + std::optional last() { + std::optional value; + for (auto n = next(); n.has_value(); n = next()) + value = n; + return value; + } + + auto step_by(int32_t s) { + return iterator{[s, c = s, it = std::move(iter)]() mutable -> auto { + for (; c < s; c++) + it(); + c = 1; + return it(); + }}; + } + + auto chain(iterator&& i) { + return iterator{[it1 = std::move(iter), it2 = std::move(i.iter), s = true]() mutable -> auto { + if (s) { + auto v = it1(true); + if (!v.has_value()) { + s = false; + return it2(true); + } + } else + return it2(true); + }}; + } + + template + auto zip(iterator&& i) { + return iterator>{[it1 = std::move(iter), it2 = std::move(i.iter)]() mutable -> auto { + if(auto v1 = it1(); v1.has_value()) { + if(auto v2 = it2(); v2.has_value()) + return std::optional>(std::make_pair(v1.value(), v2.value())); + } + return std::optional>(); + }}; + } + + template + void for_each(F f) { + for(auto v = next(); v.has_value(); v = next()) { + InvokeType().CallNoReturn(std::ref(f), v.value()); + } + } + + template + auto filter(F f) { + return iterator{[f, it = std::move(iter)]() mutable -> auto { + auto value = it(); + while(value.has_value() && !InvokeType().Call(std::ref(f), value.value())) + value = it(); + return value; + }}; + } + + template + auto map(M m) { + using RET = typename FunctionType::return_type; + return iterator{[m, it = std::move(iter)]() -> auto { + auto t = it(); + if (t.has_value()) + return std::optional(InvokeType().Call(std::ref(m), t.value())); + return std::optional(); + }}; + } + + template + auto filter_map(FM fm) { + using OPT = typename FunctionType::return_type; + static_assert(TemplateChecker::value, "filter_map: filter must return an optional value."); + using RET = typename OPT::value_type; + return iterator{[fm, it = std::move(iter)]() -> auto { + auto value = it(); + while (value.has_value()) { + if(auto mvalue = InvokeType().Call(std::ref(fm), value.value()); mvalue.has_value()) + return mvalue; + value = it(); + } + return std::optional(); + }}; + } + + auto enumerate() { + return iterator>{[it = std::move(iter), i = 0]() mutable -> auto { + if(auto v = it(); v.has_value()) + return std::optional>(std::make_pair(i++, v.value())); + return std::optional>(); + }}; + } + + auto skip(size_t n) { + return iterator{[n, it = std::move(iter)]() mutable -> auto { + while (n > 0) { + n--; + it(); + } + return it(); + }}; + } + + auto take(size_t n) { + return iterator{[n, it = std::move(iter)]() mutable -> auto { + if (n > 0) { + n--; + return it(); + } + return std::optional(); + }}; + } + + template + auto skip_while(F f) { + return iterator{[f, it = std::move(iter), res = false]() mutable -> auto { + auto v = it(); + if(res) + return v; + while(v.has_value() && InvokeType().Call(std::ref(f), v.value())) + v = it(); + res = true; + return v; + }}; + } + + template + auto take_while(F f) { + return iterator{[f, it = std::move(iter), res = true]() mutable -> auto { + if (res) { + if(auto v = it(); v.has_value() && InvokeType().Call(std::ref(f), v.value())) + return v; + else + res = false; + } + return std::optional(); + }}; + } + + template + auto scan(S s, M m) { + using RET = typename FunctionType::return_type; + return iterator{[s, m, it = std::move(iter)]() mutable -> auto { + auto t = it(); + if(t.has_value()) + return std::optional(InvokeType().CallFold(std::ref(m), std::ref(s), t.value())); + return std::optional(); + }}; + } + + template + auto flat_map(M m) { + return map(m).flatten(); + } + + auto flatten() { + static_assert(TemplateChecker::value, "flatten: value type can only be iterator type."); + using NT = typename T::value_type; + return iterator{[inited = false, cur = std::optional>(), it = std::move(iter)]() mutable -> auto { + if(!inited) { + cur = it(); + inited = true; + } + if(!cur.has_value()) + return std::optional(); + auto v = cur.value().next(); + while(!v.has_value() && cur.has_value()) { + cur = it(); + if(cur.has_value()) + v = cur.value().next(); + } + return v; + }}; + } + + auto fuse() { + return iterator{[end = false, it = std::move(iter)]() mutable -> auto { + if (end) + return std::optional(); + auto v = it(); + if(!it.has_value()) + end = true; + return v; + }}; + } + + template + auto inspect(F f) { + return iterator{[f, it = std::move(iter)]() -> auto { + auto v = it(); + if(v.has_value()) + InvokeType().CallNoReturn(std::ref(f), v.value()); + return v; + }}; + } + + template + auto collect() { + C container; + for (auto v = next(); v.has_value(); v = next()) + container.collect_item(v.value()); + return container; + } + + template + C& collect(C& container) { + for (auto v = next(); v.has_value(); v = next()) + container.collect_item(v.value()); + return container; + } + + template + auto partition(F f) { + std::pair result; + for (auto v = next(); v.has_value(); v = next()) { + if(InvokeType().CallNoReturn(std::ref(f), v.value())) + result.first.collect_item(v.value()); + else + result.second.collect_item(v.value()); + } + return result; + } + + template + auto fold(S s, F f) { + using RET = typename FunctionType::return_type; + static_assert(std::is_same::value, "fold: function should return same type as value."); + for (auto v = next(); v.has_value(); v = next()) { + s = InvokeType().CallFold(std::ref(f), s, v.value()); + } + return s; + } + + template + bool all(F f) { + for (auto v = next(); v.has_value(); v = next()) { + if(!InvokeType().Call(std::ref(f), v.value())) + return false; + } + return true; + } + + template + bool any(F f) { + for (auto v = next(); v.has_value(); v = next()) { + if(InvokeType().Call(std::ref(f), v.value())) + return true; + } + return false; + } + + template + auto find(F f) { + for (auto v = next(); v.has_value(); v = next()) { + if(InvokeType().Call(std::ref(f), v.value())) + return v; + } + return std::optional(); + } + + template + auto find_map(F f) { + using OPT = typename FunctionType::return_type; + static_assert(TemplateChecker::value, "find_map: filter must return an optional value."); + using RET = typename OPT::value_type; + for (auto v = next(); v.has_value(); v = next()) { + if(auto mv = InvokeType().Call(std::ref(f), v.value()); mv.has_value()) + return mv; + } + return std::optional(); + } + + template + auto position(F f) { + size_t i = 0; + for (auto v = next(); v.has_value(); v = next(), i++) { + if(InvokeType().Call(std::ref(f), v.value())) + return std::optional(i); + } + return std::optional(); + } + + auto max() { + auto res = next(); + if(!res.has_value()) + return res; + for (auto v = next(); v.has_value(); v = next()) { + if(v.value() >= res.value()) + res = v; + } + return res; + } + + auto min() { + auto res = next(); + if(!res.has_value()) + return res; + for (auto v = next(); v.has_value(); v = next()) { + if(v.value() < res.value()) + res = v; + } + return res; + } + + template + auto max_by_key(F f) { + auto res = next(); + if(!res.has_value()) + return res; + for (auto v = next(); v.has_value(); v = next()) { + if(InvokeType().Call(std::ref(f), v.value()) >= InvokeType().Call(std::ref(f), res.value())) + res = v; + } + return res; + } + + template + auto min_by_key(F f) { + auto res = next(); + if(!res.has_value()) + return res; + for (auto v = next(); v.has_value(); v = next()) { + if(InvokeType().Call(std::ref(f), v.value()) < InvokeType().Call(std::ref(f), res.value())) + res = v; + } + return res; + } + + auto unzip() { + static_assert(TemplateChecker::value, "unzip: iterator type must be pair"); + using TP1 = typename T::first_type; + using TP2 = typename T::second_type; + std::pair, iterator> result; + result.first.iter = [it = iter]()-> auto { + auto v = it(); + return v.has_value() ? std::optional(v.value().first): std::optional(); + }; + result.second.iter = [it = iter]()-> auto { + auto v = it(); + return v.has_value() ? std::optional(v.value().second): std::optional(); + }; + return result; + } + + auto cycle() { + return iterator{[it = iter, it2 = iter]() mutable -> auto { + auto v = it(false); + if(v.has_value()) + return v; + it = it2; + return it(false); + }}; + } + + auto sum() { + auto res = T(0); + for (auto v = next(); v.has_value(); v = next()) + res += v.value(); + return res; + } + + auto product() { + auto res = T(1); + for (auto v = next(); v.has_value(); v = next()) + res *= v.value(); + return res; + } + + std::function()> iter; +}; + +template +auto range(T start, T end) { + return iterator{[start, end]() mutable -> auto { + if(start >= end) + return std::optional(); + return std::optional(start++); + }}; +} + +template +auto repeat(T value) { + return iterator{[value]() -> auto { + return std::optional(value); + }}; +} + +} // namespace rs +#endif diff --git a/rusty.hpp b/rusty.hpp new file mode 100644 index 0000000..a34788b --- /dev/null +++ b/rusty.hpp @@ -0,0 +1,258 @@ +#ifndef _RC_HPP_ +#define _RC_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rs_iter.hpp" + +namespace rs { + +template +class linear_container : public P { +public: + using P::P; + + template + rs::iterator into_iter() const { + if constexpr (!REV) { + return rs::iterator{[this, iter = this->begin()] () mutable -> auto { + if(iter == this->end()) + return std::optional(); + return std::optional(*iter++); + }}; + } else { + return rs::iterator{[this, riter = this->rbegin()] () mutable -> auto { + if(riter == this->rend()) + return std::optional(); + return std::optional(*riter++); + }}; + } + } + + template + rs::iterator into_iter_ptr() const { + if constexpr (!REV) { + return rs::iterator{[this, iter = this->cbegin()] () mutable -> auto { + if(iter == this->cend()) + return std::optional(); + return std::optional(&*iter++); + }}; + } else { + return rs::iterator{[this, riter = this->crbegin()] () mutable -> auto { + if(riter == this->crend()) + return std::optional(); + return std::optional(&*riter++); + }}; + } + } + + template + rs::iterator into_iter_mptr() { + if constexpr (!REV) { + return rs::iterator{[this, iter = this->begin()] () mutable -> auto { + if(iter == this->end()) + return std::optional(); + return std::optional(&*iter++); + }}; + } else { + return rs::iterator{[this, riter = this->rbegin()] () mutable -> auto { + if(riter == this->rend()) + return std::optional(); + return std::optional(&*riter++); + }}; + } + } + + void collect_item(const TP& v) { + this->push_back(v); + } +}; + +template > +using vector = linear_container, TP>; +template > +using list = linear_container, TP>; +template > +using forward_list = linear_container, TP>; +template > +using deque = linear_container, TP>; +template +using array = linear_container, TP>; + +template +class set_container : public S { +public: + using S::S; + + template + rs::iterator into_iter() const { + if constexpr (!REV || !CanRev) { + return rs::iterator{[this, iter = this->begin()] () mutable -> auto { + if(iter == this->end()) + return std::optional(); + return std::optional(*iter++); + }}; + } else { + return rs::iterator{[this, riter = this->rbegin()] () mutable -> auto { + if(riter == this->rend()) + return std::optional(); + return std::optional(*riter++); + }}; + } + } + + template + rs::iterator into_iter_ptr() const { + if constexpr (!REV || !CanRev) { + return rs::iterator{[this, iter = this->cbegin()] () mutable -> auto { + if(iter == this->cend()) + return std::optional(); + return std::optional(&*iter++); + }}; + } else { + return rs::iterator{[this, riter = this->crbegin()] () mutable -> auto { + if(riter == this->crend()) + return std::optional(); + return std::optional(&*riter++); + }}; + } + } + + void collect_item(const KEY& value) { + this->insert(value); + } + +}; + +template, + typename ALLOC = std::allocator> +using set = set_container, KEY, true>; +template, + typename ALLOC = std::allocator> +using multiset = set_container, KEY, true>; +template, + typename PRED = std::equal_to, + typename ALLOC = std::allocator> +using unordered_set = set_container, KEY, false>; +template, + typename PRED = std::equal_to, + typename ALLOC = std::allocator> +using unordered_multiset = set_container, KEY, false>; + +template +class map_container : public M { +public: + using M::M; + + template + rs::iterator> into_iter() const { + if constexpr (!REV || !CanRev) { + return rs::iterator>{[this, iter = this->begin()] () mutable -> auto { + if(iter == this->end()) + return std::optional>(); + return std::optional>(*iter++); + }}; + } else { + return rs::iterator>{[this, riter = this->rbegin()] () mutable -> auto { + if(riter == this->rend()) + return std::optional>(); + return std::optional>(*riter++); + }}; + } + } + + template + rs::iterator> into_iter_ptr() const { + if constexpr (!REV || !CanRev) { + return rs::iterator>{[this, iter = this->cbegin()] (bool rev) mutable -> auto { + if(iter == this->cend()) + return std::optional>(); + auto ptr = &*iter++; + return std::optional>(std::make_pair(&ptr->first, &ptr->second)); + }}; + } else { + return rs::iterator>{[this, riter = this->crbegin()] (bool rev) mutable -> auto { + if(riter == this->crend()) + return std::optional>(); + auto ptr = &*riter++; + return std::optional>(std::make_pair(&ptr->first, &ptr->second)); + }}; + } + } + + template + rs::iterator> into_iter_mptr() { + if constexpr (!REV || !CanRev) { + return rs::iterator>{[this, iter = this->begin()] (bool rev) mutable -> auto { + if(iter == this->end()) + return std::optional>(); + auto ptr = &*iter++; + return std::optional>(std::make_pair(&ptr->first, &ptr->second)); + }}; + } else { + return rs::iterator>{[this, riter = this->rbegin()] (bool rev) mutable -> auto { + if(riter == this->rend()) + return std::optional>(); + auto ptr = &*riter++; + return std::optional>(std::make_pair(&ptr->first, &ptr->second)); + }}; + } + } + + rs::iterator keys() const { + return into_iter().unzip().first; + } + + rs::iterator keys_ptr() const { + return into_iter_ptr().unzip().first; + } + + rs::iterator values() const { + return into_iter().unzip().second; + } + + rs::iterator values_ptr() const { + return into_iter_ptr().unzip().second; + } + + void collect_item(const std::pair& value) { + this->insert(value); + } + +}; + +template, + typename ALLOC = std::allocator>> +using map = map_container, KEY, TP, true>; +template, + typename ALLOC = std::allocator>> +using multimap = map_container, KEY, TP, true>; +template, + typename PRED = std::equal_to, + typename ALLOC = std::allocator>> +using unordered_map = map_container, KEY, TP, false>; +template, + typename PRED = std::equal_to, + typename ALLOC = std::allocator>> +using unordered_multimap = map_container, KEY, TP, false>; + +} + +#endif