rusty/rusty.hpp

259 lines
9.5 KiB
C++

#ifndef _RC_HPP_
#define _RC_HPP_
#include <array>
#include <vector>
#include <list>
#include <forward_list>
#include <deque>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <string>
#include "rs_iter.hpp"
namespace rs {
template<typename P, typename TP>
class linear_container : public P {
public:
using P::P;
template<bool REV = false>
rs::iterator<TP> into_iter() const {
if constexpr (!REV) {
return rs::iterator<TP>{[this, iter = this->begin()] () mutable -> auto {
if(iter == this->end())
return std::optional<TP>();
return std::optional<TP>(*iter++);
}};
} else {
return rs::iterator<TP>{[this, riter = this->rbegin()] () mutable -> auto {
if(riter == this->rend())
return std::optional<TP>();
return std::optional<TP>(*riter++);
}};
}
}
template<bool REV = false>
rs::iterator<const TP*> into_iter_ptr() const {
if constexpr (!REV) {
return rs::iterator<const TP*>{[this, iter = this->cbegin()] () mutable -> auto {
if(iter == this->cend())
return std::optional<const TP*>();
return std::optional<const TP*>(&*iter++);
}};
} else {
return rs::iterator<const TP*>{[this, riter = this->crbegin()] () mutable -> auto {
if(riter == this->crend())
return std::optional<const TP*>();
return std::optional<const TP*>(&*riter++);
}};
}
}
template<bool REV = false>
rs::iterator<TP*> into_iter_mptr() {
if constexpr (!REV) {
return rs::iterator<TP*>{[this, iter = this->begin()] () mutable -> auto {
if(iter == this->end())
return std::optional<TP*>();
return std::optional<TP*>(&*iter++);
}};
} else {
return rs::iterator<TP*>{[this, riter = this->rbegin()] () mutable -> auto {
if(riter == this->rend())
return std::optional<TP*>();
return std::optional<TP*>(&*riter++);
}};
}
}
void collect_item(const TP& v) {
this->push_back(v);
}
};
template <typename TP, typename ALLOC = std::allocator<TP>>
using vector = linear_container<std::vector<TP, ALLOC>, TP>;
template <typename TP, typename ALLOC = std::allocator<TP>>
using list = linear_container<std::list<TP, ALLOC>, TP>;
template <typename TP, typename ALLOC = std::allocator<TP>>
using forward_list = linear_container<std::forward_list<TP, ALLOC>, TP>;
template <typename TP, typename ALLOC = std::allocator<TP>>
using deque = linear_container<std::deque<TP, ALLOC>, TP>;
template <typename TP, size_t COUNT>
using array = linear_container<std::array<TP, COUNT>, TP>;
template<typename S, typename KEY, bool CanRev>
class set_container : public S {
public:
using S::S;
template<bool REV = false>
rs::iterator<KEY> into_iter() const {
if constexpr (!REV || !CanRev) {
return rs::iterator<KEY>{[this, iter = this->begin()] () mutable -> auto {
if(iter == this->end())
return std::optional<KEY>();
return std::optional<KEY>(*iter++);
}};
} else {
return rs::iterator<KEY>{[this, riter = this->rbegin()] () mutable -> auto {
if(riter == this->rend())
return std::optional<KEY>();
return std::optional<KEY>(*riter++);
}};
}
}
template<bool REV = false>
rs::iterator<const KEY*> into_iter_ptr() const {
if constexpr (!REV || !CanRev) {
return rs::iterator<const KEY*>{[this, iter = this->cbegin()] () mutable -> auto {
if(iter == this->cend())
return std::optional<const KEY*>();
return std::optional<const KEY*>(&*iter++);
}};
} else {
return rs::iterator<const KEY*>{[this, riter = this->crbegin()] () mutable -> auto {
if(riter == this->crend())
return std::optional<const KEY*>();
return std::optional<const KEY*>(&*riter++);
}};
}
}
void collect_item(const KEY& value) {
this->insert(value);
}
};
template<typename KEY,
typename COMPARE = std::less<KEY>,
typename ALLOC = std::allocator<KEY>>
using set = set_container<std::set<KEY, COMPARE, ALLOC>, KEY, true>;
template<typename KEY,
typename COMPARE = std::less<KEY>,
typename ALLOC = std::allocator<KEY>>
using multiset = set_container<std::multiset<KEY, COMPARE, ALLOC>, KEY, true>;
template<typename KEY,
typename HASH = std::hash<KEY>,
typename PRED = std::equal_to<KEY>,
typename ALLOC = std::allocator<KEY>>
using unordered_set = set_container<std::unordered_set<KEY, HASH, PRED, ALLOC>, KEY, false>;
template<typename KEY, typename TP,
typename HASH = std::hash<KEY>,
typename PRED = std::equal_to<KEY>,
typename ALLOC = std::allocator<KEY>>
using unordered_multiset = set_container<std::unordered_multiset<KEY, HASH, PRED, ALLOC>, KEY, false>;
template<typename M, typename KEY, typename TP, bool CanRev>
class map_container : public M {
public:
using M::M;
template<bool REV = false>
rs::iterator<std::pair<KEY, TP>> into_iter() const {
if constexpr (!REV || !CanRev) {
return rs::iterator<std::pair<KEY, TP>>{[this, iter = this->begin()] () mutable -> auto {
if(iter == this->end())
return std::optional<std::pair<KEY, TP>>();
return std::optional<std::pair<KEY, TP>>(*iter++);
}};
} else {
return rs::iterator<std::pair<KEY, TP>>{[this, riter = this->rbegin()] () mutable -> auto {
if(riter == this->rend())
return std::optional<std::pair<KEY, TP>>();
return std::optional<std::pair<KEY, TP>>(*riter++);
}};
}
}
template<bool REV = false>
rs::iterator<std::pair<const KEY*, const TP*>> into_iter_ptr() const {
if constexpr (!REV || !CanRev) {
return rs::iterator<std::pair<const KEY*, const TP*>>{[this, iter = this->cbegin()] (bool rev) mutable -> auto {
if(iter == this->cend())
return std::optional<std::pair<const KEY*, const TP*>>();
auto ptr = &*iter++;
return std::optional<std::pair<const KEY*, const TP*>>(std::make_pair(&ptr->first, &ptr->second));
}};
} else {
return rs::iterator<std::pair<const KEY*, const TP*>>{[this, riter = this->crbegin()] (bool rev) mutable -> auto {
if(riter == this->crend())
return std::optional<std::pair<const KEY*, const TP*>>();
auto ptr = &*riter++;
return std::optional<std::pair<const KEY*, const TP*>>(std::make_pair(&ptr->first, &ptr->second));
}};
}
}
template<bool REV = false>
rs::iterator<std::pair<const KEY*, TP*>> into_iter_mptr() {
if constexpr (!REV || !CanRev) {
return rs::iterator<std::pair<const KEY*, const TP*>>{[this, iter = this->begin()] (bool rev) mutable -> auto {
if(iter == this->end())
return std::optional<std::pair<const KEY*, const TP*>>();
auto ptr = &*iter++;
return std::optional<std::pair<const KEY*, const TP*>>(std::make_pair(&ptr->first, &ptr->second));
}};
} else {
return rs::iterator<std::pair<const KEY*, const TP*>>{[this, riter = this->rbegin()] (bool rev) mutable -> auto {
if(riter == this->rend())
return std::optional<std::pair<const KEY*, const TP*>>();
auto ptr = &*riter++;
return std::optional<std::pair<const KEY*, const TP*>>(std::make_pair(&ptr->first, &ptr->second));
}};
}
}
rs::iterator<KEY> keys() const {
return into_iter().unzip().first;
}
rs::iterator<const KEY*> keys_ptr() const {
return into_iter_ptr().unzip().first;
}
rs::iterator<TP> values() const {
return into_iter().unzip().second;
}
rs::iterator<const TP*> values_ptr() const {
return into_iter_ptr().unzip().second;
}
void collect_item(const std::pair<KEY, TP>& value) {
this->insert(value);
}
};
template<typename KEY, typename TP,
typename COMPARE = std::less<KEY>,
typename ALLOC = std::allocator<std::pair<const KEY, TP>>>
using map = map_container<std::map<KEY, TP, COMPARE, ALLOC>, KEY, TP, true>;
template<typename KEY, typename TP,
typename COMPARE = std::less<KEY>,
typename ALLOC = std::allocator<std::pair<const KEY, TP>>>
using multimap = map_container<std::multimap<KEY, TP, COMPARE, ALLOC>, KEY, TP, true>;
template<typename KEY, typename TP,
typename HASH = std::hash<KEY>,
typename PRED = std::equal_to<KEY>,
typename ALLOC = std::allocator<std::pair<const KEY, TP>>>
using unordered_map = map_container<std::unordered_map<KEY, TP, HASH, PRED, ALLOC>, KEY, TP, false>;
template<typename KEY, typename TP,
typename HASH = std::hash<KEY>,
typename PRED = std::equal_to<KEY>,
typename ALLOC = std::allocator<std::pair<const KEY, TP>>>
using unordered_multimap = map_container<std::unordered_multimap<KEY, TP, HASH, PRED, ALLOC>, KEY, TP, false>;
}
#endif