259 lines
9.3 KiB
C++
259 lines
9.3 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 {
|
||
|
if(iter == this->end())
|
||
|
return std::optional<TP>();
|
||
|
return std::optional<TP>(*iter++);
|
||
|
}};
|
||
|
} else {
|
||
|
return rs::iterator<TP>{[this, riter = this->rbegin()] () mutable {
|
||
|
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 {
|
||
|
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 {
|
||
|
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 {
|
||
|
if(iter == this->end())
|
||
|
return std::optional<TP*>();
|
||
|
return std::optional<TP*>(&*iter++);
|
||
|
}};
|
||
|
} else {
|
||
|
return rs::iterator<TP*>{[this, riter = this->rbegin()] () mutable {
|
||
|
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 {
|
||
|
if(iter == this->end())
|
||
|
return std::optional<KEY>();
|
||
|
return std::optional<KEY>(*iter++);
|
||
|
}};
|
||
|
} else {
|
||
|
return rs::iterator<KEY>{[this, riter = this->rbegin()] () mutable {
|
||
|
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 {
|
||
|
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 {
|
||
|
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 {
|
||
|
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 {
|
||
|
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 {
|
||
|
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 {
|
||
|
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 {
|
||
|
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 {
|
||
|
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
|