osb/source/core/StarList.hpp
2023-06-27 20:23:44 +10:00

1142 lines
33 KiB
C++

#ifndef STAR_LIST_HPP
#define STAR_LIST_HPP
#include <vector>
#include <deque>
#include <list>
#include "StarException.hpp"
#include "StarStaticVector.hpp"
#include "StarSmallVector.hpp"
#include "StarPythonic.hpp"
#include "StarMaybe.hpp"
#include "StarFormat.hpp"
namespace Star {
template <typename BaseList>
class ListMixin : public BaseList {
public:
typedef BaseList Base;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
typedef typename Base::value_type value_type;
typedef typename Base::reference reference;
typedef typename Base::const_reference const_reference;
ListMixin();
ListMixin(Base const& list);
ListMixin(Base&& list);
ListMixin(value_type const* p, size_t count);
template <typename InputIterator>
ListMixin(InputIterator beg, InputIterator end);
explicit ListMixin(size_t len, const_reference s1 = value_type());
ListMixin(initializer_list<value_type> list);
void append(value_type e);
template <typename Container>
void appendAll(Container&& list);
template <class... Args>
reference emplaceAppend(Args&&... args);
reference first();
const_reference first() const;
reference last();
const_reference last() const;
Maybe<value_type> maybeFirst();
Maybe<value_type> maybeLast();
void removeLast();
value_type takeLast();
Maybe<value_type> maybeTakeLast();
// Limit the size of the list by removing elements from the back until the
// size is the maximumSize or less.
void limitSizeBack(size_t maximumSize);
size_t count() const;
bool contains(const_reference e) const;
// Remove all equal to element, returns number removed.
size_t remove(const_reference e);
template <typename Filter>
void filter(Filter&& filter);
template <typename Comparator>
void insertSorted(value_type e, Comparator&& comparator);
void insertSorted(value_type e);
// Returns true if this *sorted* list contains the given element.
template <typename Comparator>
bool containsSorted(value_type const& e, Comparator&& comparator);
bool containsSorted(value_type e);
template <typename Function>
void exec(Function&& function);
template <typename Function>
void exec(Function&& function) const;
template <typename Function>
void transform(Function&& function);
template <typename Function>
bool any(Function&& function) const;
bool any() const;
template <typename Function>
bool all(Function&& function) const;
bool all() const;
};
template <typename List>
class ListHasher {
public:
size_t operator()(List const& l) const;
private:
hash<typename List::value_type> elemHasher;
};
template <typename BaseList>
class RandomAccessListMixin : public BaseList {
public:
typedef BaseList Base;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
typedef typename Base::value_type value_type;
typedef typename Base::reference reference;
typedef typename Base::const_reference const_reference;
using Base::Base;
template <typename Comparator>
void sort(Comparator&& comparator);
void sort();
void reverse();
// Returns first index of given element, NPos if not found.
size_t indexOf(const_reference e, size_t from = 0) const;
// Returns last index of given element, NPos if not found.
size_t lastIndexOf(const_reference e, size_t til = NPos) const;
const_reference at(size_t n) const;
reference at(size_t n);
const_reference operator[](size_t n) const;
reference operator[](size_t n);
// Does not throw if n is beyond end of list, instead returns def
value_type get(size_t n, value_type def = value_type()) const;
value_type takeAt(size_t i);
// Same as at, but wraps around back to the beginning
// (throws if list is empty)
const_reference wrap(size_t n) const;
reference wrap(size_t n);
// Does not throw if list is empty
value_type wrap(size_t n, value_type def) const;
void eraseAt(size_t index);
// Erases region from begin to end, not including end.
void eraseAt(size_t begin, size_t end);
void insertAt(size_t pos, value_type e);
template <typename Container>
void insertAllAt(size_t pos, Container const& l);
// Ensures that list is large enough to hold pos elements.
void set(size_t pos, value_type e);
void swap(size_t i, size_t j);
// same as insert(to, takeAt(from))
void move(size_t from, size_t to);
};
template <typename BaseList>
class FrontModifyingListMixin : public BaseList {
public:
typedef BaseList Base;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
typedef typename Base::value_type value_type;
typedef typename Base::reference reference;
typedef typename Base::const_reference const_reference;
using Base::Base;
void prepend(value_type e);
template <typename Container>
void prependAll(Container&& list);
template <class... Args>
reference emplacePrepend(Args&&... args);
void removeFirst();
value_type takeFirst();
// Limit the size of the list by removing elements from the front until the
// size is the maximumSize or less.
void limitSizeFront(size_t maximumSize);
};
template <typename Element, typename Allocator = std::allocator<Element>>
class List : public RandomAccessListMixin<ListMixin<std::vector<Element, Allocator>>> {
public:
typedef RandomAccessListMixin<ListMixin<std::vector<Element, Allocator>>> Base;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
typedef typename Base::value_type value_type;
typedef typename Base::reference reference;
typedef typename Base::const_reference const_reference;
template <typename Container>
static List from(Container const& c);
using Base::Base;
// Pointer to contiguous storage, returns nullptr if empty
value_type* ptr();
value_type const* ptr() const;
List slice(SliceIndex a = SliceIndex(), SliceIndex b = SliceIndex(), int i = 1) const;
template <typename Filter>
List filtered(Filter&& filter) const;
template <typename Comparator>
List sorted(Comparator&& comparator) const;
List sorted() const;
template <typename Function>
auto transformed(Function&& function);
template <typename Function>
auto transformed(Function&& function) const;
};
template <typename Element, typename Allocator>
struct hash<List<Element, Allocator>> : public ListHasher<List<Element, Allocator>> {};
template <typename Element, size_t MaxSize>
class StaticList : public RandomAccessListMixin<ListMixin<StaticVector<Element, MaxSize>>> {
public:
typedef RandomAccessListMixin<ListMixin<StaticVector<Element, MaxSize>>> Base;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
typedef typename Base::value_type value_type;
typedef typename Base::reference reference;
typedef typename Base::const_reference const_reference;
template <typename Container>
static StaticList from(Container const& c);
using Base::Base;
StaticList slice(SliceIndex a = SliceIndex(), SliceIndex b = SliceIndex(), int i = 1) const;
template <typename Filter>
StaticList filtered(Filter&& filter) const;
template <typename Comparator>
StaticList sorted(Comparator&& comparator) const;
StaticList sorted() const;
template <typename Function>
auto transformed(Function&& function);
template <typename Function>
auto transformed(Function&& function) const;
};
template <typename Element, size_t MaxStackSize>
struct hash<StaticList<Element, MaxStackSize>> : public ListHasher<StaticList<Element, MaxStackSize>> {};
template <typename Element, size_t MaxStackSize>
class SmallList : public RandomAccessListMixin<ListMixin<SmallVector<Element, MaxStackSize>>> {
public:
typedef RandomAccessListMixin<ListMixin<SmallVector<Element, MaxStackSize>>> Base;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
typedef typename Base::value_type value_type;
typedef typename Base::reference reference;
typedef typename Base::const_reference const_reference;
template <typename Container>
static SmallList from(Container const& c);
using Base::Base;
SmallList slice(SliceIndex a = SliceIndex(), SliceIndex b = SliceIndex(), int i = 1) const;
template <typename Filter>
SmallList filtered(Filter&& filter) const;
template <typename Comparator>
SmallList sorted(Comparator&& comparator) const;
SmallList sorted() const;
template <typename Function>
auto transformed(Function&& function);
template <typename Function>
auto transformed(Function&& function) const;
};
template <typename Element, size_t MaxStackSize>
struct hash<SmallList<Element, MaxStackSize>> : public ListHasher<SmallList<Element, MaxStackSize>> {};
template <typename Element, typename Allocator = std::allocator<Element>>
class Deque : public FrontModifyingListMixin<RandomAccessListMixin<ListMixin<std::deque<Element, Allocator>>>> {
public:
typedef FrontModifyingListMixin<RandomAccessListMixin<ListMixin<std::deque<Element, Allocator>>>> Base;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
typedef typename Base::value_type value_type;
typedef typename Base::reference reference;
typedef typename Base::const_reference const_reference;
template <typename Container>
static Deque from(Container const& c);
using Base::Base;
Deque slice(SliceIndex a = SliceIndex(), SliceIndex b = SliceIndex(), int i = 1) const;
template <typename Filter>
Deque filtered(Filter&& filter) const;
template <typename Comparator>
Deque sorted(Comparator&& comparator) const;
Deque sorted() const;
template <typename Function>
auto transformed(Function&& function);
template <typename Function>
auto transformed(Function&& function) const;
};
template <typename Element, typename Allocator>
struct hash<Deque<Element, Allocator>> : public ListHasher<Deque<Element, Allocator>> {};
template <typename Element, typename Allocator = std::allocator<Element>>
class LinkedList : public FrontModifyingListMixin<ListMixin<std::list<Element, Allocator>>> {
public:
typedef FrontModifyingListMixin<ListMixin<std::list<Element, Allocator>>> Base;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
typedef typename Base::value_type value_type;
typedef typename Base::reference reference;
typedef typename Base::const_reference const_reference;
template <typename Container>
static LinkedList from(Container const& c);
using Base::Base;
void appendAll(LinkedList list);
void prependAll(LinkedList list);
template <typename Container>
void appendAll(Container&& list);
template <typename Container>
void prependAll(Container&& list);
template <typename Filter>
LinkedList filtered(Filter&& filter) const;
template <typename Comparator>
LinkedList sorted(Comparator&& comparator) const;
LinkedList sorted() const;
template <typename Function>
auto transformed(Function&& function);
template <typename Function>
auto transformed(Function&& function) const;
};
template <typename Element, typename Allocator>
struct hash<LinkedList<Element, Allocator>> : public ListHasher<LinkedList<Element, Allocator>> {};
template <typename BaseList>
std::ostream& operator<<(std::ostream& os, ListMixin<BaseList> const& list);
template <typename... Containers>
struct ListZipTypes {
typedef tuple<typename std::decay<Containers>::type::value_type...> Tuple;
typedef List<Tuple> Result;
};
template <typename... Containers>
typename ListZipTypes<Containers...>::Result zip(Containers&&... args);
template <typename Container>
struct ListEnumerateTypes {
typedef pair<typename std::decay<Container>::type::value_type, size_t> Pair;
typedef List<Pair> Result;
};
template <typename Container>
typename ListEnumerateTypes<Container>::Result enumerate(Container&& container);
template <typename BaseList>
ListMixin<BaseList>::ListMixin()
: Base() {}
template <typename BaseList>
ListMixin<BaseList>::ListMixin(Base const& list)
: Base(list) {}
template <typename BaseList>
ListMixin<BaseList>::ListMixin(Base&& list)
: Base(std::move(list)) {}
template <typename BaseList>
ListMixin<BaseList>::ListMixin(size_t len, const_reference s1)
: Base(len, s1) {}
template <typename BaseList>
ListMixin<BaseList>::ListMixin(value_type const* p, size_t count)
: Base(p, p + count) {}
template <typename BaseList>
template <typename InputIterator>
ListMixin<BaseList>::ListMixin(InputIterator beg, InputIterator end)
: Base(beg, end) {}
template <typename BaseList>
ListMixin<BaseList>::ListMixin(initializer_list<value_type> list) {
// In case underlying class type doesn't support initializer_list
for (auto& e : list)
append(std::move(e));
}
template <typename BaseList>
void ListMixin<BaseList>::append(value_type e) {
Base::push_back(std::move(e));
}
template <typename BaseList>
template <typename Container>
void ListMixin<BaseList>::appendAll(Container&& list) {
for (auto& e : list) {
if (std::is_rvalue_reference<Container&&>::value)
Base::push_back(std::move(e));
else
Base::push_back(e);
}
}
template <typename BaseList>
template <class... Args>
auto ListMixin<BaseList>::emplaceAppend(Args&&... args) -> reference {
Base::emplace_back(forward<Args>(args)...);
return *prev(Base::end());
}
template <typename BaseList>
auto ListMixin<BaseList>::first() -> reference {
if (Base::empty())
throw OutOfRangeException("first() called on empty list");
return *Base::begin();
}
template <typename BaseList>
auto ListMixin<BaseList>::first() const -> const_reference {
if (Base::empty())
throw OutOfRangeException("first() called on empty list");
return *Base::begin();
}
template <typename BaseList>
auto ListMixin<BaseList>::last() -> reference {
if (Base::empty())
throw OutOfRangeException("last() called on empty list");
return *prev(Base::end());
}
template <typename BaseList>
auto ListMixin<BaseList>::last() const -> const_reference {
if (Base::empty())
throw OutOfRangeException("last() called on empty list");
return *prev(Base::end());
}
template <typename BaseList>
auto ListMixin<BaseList>::maybeFirst() -> Maybe<value_type> {
if (Base::empty())
return {};
return *Base::begin();
}
template <typename BaseList>
auto ListMixin<BaseList>::maybeLast() -> Maybe<value_type> {
if (Base::empty())
return {};
return *prev(Base::end());
}
template <typename BaseList>
void ListMixin<BaseList>::removeLast() {
if (Base::empty())
throw OutOfRangeException("removeLast() called on empty list");
Base::pop_back();
}
template <typename BaseList>
auto ListMixin<BaseList>::takeLast() -> value_type {
value_type e = std::move(last());
Base::pop_back();
return e;
}
template <typename BaseList>
auto ListMixin<BaseList>::maybeTakeLast() -> Maybe<value_type> {
if (Base::empty())
return {};
value_type e = std::move(last());
Base::pop_back();
return e;
}
template <typename BaseList>
void ListMixin<BaseList>::limitSizeBack(size_t maximumSize) {
while (Base::size() > maximumSize)
Base::pop_back();
}
template <typename BaseList>
size_t ListMixin<BaseList>::count() const {
return Base::size();
}
template <typename BaseList>
bool ListMixin<BaseList>::contains(const_reference e) const {
for (auto const& r : *this) {
if (r == e)
return true;
}
return false;
}
template <typename BaseList>
size_t ListMixin<BaseList>::remove(const_reference e) {
size_t removed = 0;
auto i = Base::begin();
while (i != Base::end()) {
if (*i == e) {
++removed;
i = Base::erase(i);
} else {
++i;
}
}
return removed;
}
template <typename BaseList>
template <typename Filter>
void ListMixin<BaseList>::filter(Filter&& filter) {
Star::filter(*this, forward<Filter>(filter));
}
template <typename BaseList>
template <typename Comparator>
void ListMixin<BaseList>::insertSorted(value_type e, Comparator&& comparator) {
auto i = std::upper_bound(Base::begin(), Base::end(), e, forward<Comparator>(comparator));
Base::insert(i, std::move(e));
}
template <typename BaseList>
void ListMixin<BaseList>::insertSorted(value_type e) {
auto i = std::upper_bound(Base::begin(), Base::end(), e);
Base::insert(i, std::move(e));
}
template <typename BaseList>
template <typename Comparator>
bool ListMixin<BaseList>::containsSorted(value_type const& e, Comparator&& comparator) {
auto range = std::equal_range(Base::begin(), Base::end(), e, forward<Comparator>(comparator));
return range.first != range.second;
}
template <typename BaseList>
bool ListMixin<BaseList>::containsSorted(value_type e) {
auto range = std::equal_range(Base::begin(), Base::end(), e);
return range.first != range.second;
}
template <typename BaseList>
template <typename Function>
void ListMixin<BaseList>::exec(Function&& function) {
for (auto& e : *this)
function(e);
}
template <typename BaseList>
template <typename Function>
void ListMixin<BaseList>::exec(Function&& function) const {
for (auto const& e : *this)
function(e);
}
template <typename BaseList>
template <typename Function>
void ListMixin<BaseList>::transform(Function&& function) {
for (auto& e : *this)
e = function(e);
}
template <typename BaseList>
template <typename Function>
bool ListMixin<BaseList>::any(Function&& function) const {
return Star::any(*this, forward<Function>(function));
}
template <typename BaseList>
bool ListMixin<BaseList>::any() const {
return Star::any(*this);
}
template <typename BaseList>
template <typename Function>
bool ListMixin<BaseList>::all(Function&& function) const {
return Star::all(*this, forward<Function>(function));
}
template <typename BaseList>
bool ListMixin<BaseList>::all() const {
return Star::all(*this);
}
template <typename BaseList>
template <typename Comparator>
void RandomAccessListMixin<BaseList>::sort(Comparator&& comparator) {
Star::sort(*this, forward<Comparator>(comparator));
}
template <typename BaseList>
void RandomAccessListMixin<BaseList>::sort() {
Star::sort(*this);
}
template <typename BaseList>
void RandomAccessListMixin<BaseList>::reverse() {
Star::reverse(*this);
}
template <typename BaseList>
size_t RandomAccessListMixin<BaseList>::indexOf(const_reference e, size_t from) const {
for (size_t i = from; i < Base::size(); ++i)
if (operator[](i) == e)
return i;
return NPos;
}
template <typename BaseList>
size_t RandomAccessListMixin<BaseList>::lastIndexOf(const_reference e, size_t til) const {
size_t index = NPos;
size_t end = std::min(Base::size(), til);
for (size_t i = 0; i < end; ++i) {
if (operator[](i) == e)
index = i;
}
return index;
}
template <typename BaseList>
auto RandomAccessListMixin<BaseList>::at(size_t n) const -> const_reference {
if (n >= Base::size())
throw OutOfRangeException(strf("out of range list::at({})", n));
return operator[](n);
}
template <typename BaseList>
auto RandomAccessListMixin<BaseList>::at(size_t n) -> reference {
if (n >= Base::size())
throw OutOfRangeException(strf("out of range list::at({})", n));
return operator[](n);
}
template <typename BaseList>
auto RandomAccessListMixin<BaseList>::operator[](size_t n) const -> const_reference {
starAssert(n < Base::size());
return Base::operator[](n);
}
template <typename BaseList>
auto RandomAccessListMixin<BaseList>::operator[](size_t n) -> reference {
starAssert(n < Base::size());
return Base::operator[](n);
}
template <typename BaseList>
auto RandomAccessListMixin<BaseList>::get(size_t n, value_type def) const -> value_type {
if (n >= BaseList::size())
return def;
return operator[](n);
}
template <typename BaseList>
auto RandomAccessListMixin<BaseList>::takeAt(size_t i) -> value_type {
value_type e = at(i);
Base::erase(Base::begin() + i);
return e;
}
template <typename BaseList>
auto RandomAccessListMixin<BaseList>::wrap(size_t n) const -> const_reference {
if (BaseList::empty())
throw OutOfRangeException();
else
return operator[](n % BaseList::size());
}
template <typename BaseList>
auto RandomAccessListMixin<BaseList>::wrap(size_t n) -> reference {
if (BaseList::empty())
throw OutOfRangeException();
else
return operator[](n % BaseList::size());
}
template <typename BaseList>
auto RandomAccessListMixin<BaseList>::wrap(size_t n, value_type def) const -> value_type {
if (BaseList::empty())
return def;
else
return operator[](n % BaseList::size());
}
template <typename BaseList>
void RandomAccessListMixin<BaseList>::eraseAt(size_t i) {
starAssert(i < Base::size());
Base::erase(Base::begin() + i);
}
template <typename BaseList>
void RandomAccessListMixin<BaseList>::eraseAt(size_t b, size_t e) {
starAssert(b < Base::size() && e <= Base::size());
Base::erase(Base::begin() + b, Base::begin() + e);
}
template <typename BaseList>
void RandomAccessListMixin<BaseList>::insertAt(size_t pos, value_type e) {
starAssert(pos <= Base::size());
Base::insert(Base::begin() + pos, std::move(e));
}
template <typename BaseList>
template <typename Container>
void RandomAccessListMixin<BaseList>::insertAllAt(size_t pos, Container const& l) {
starAssert(pos <= Base::size());
Base::insert(Base::begin() + pos, l.begin(), l.end());
}
template <typename BaseList>
void RandomAccessListMixin<BaseList>::set(size_t pos, value_type e) {
if (pos >= Base::size())
Base::resize(pos + 1);
operator[](pos) = std::move(e);
}
template <typename BaseList>
void RandomAccessListMixin<BaseList>::swap(size_t i, size_t j) {
std::swap(operator[](i), operator[](j));
}
template <typename BaseList>
void RandomAccessListMixin<BaseList>::move(size_t from, size_t to) {
Base::insert(to, takeAt(from));
}
template <typename BaseList>
void FrontModifyingListMixin<BaseList>::prepend(value_type e) {
Base::push_front(std::move(e));
}
template <typename BaseList>
template <typename Container>
void FrontModifyingListMixin<BaseList>::prependAll(Container&& list) {
for (auto i = std::rbegin(list); i != std::rend(list); ++i) {
if (std::is_rvalue_reference<Container&&>::value)
Base::push_front(std::move(*i));
else
Base::push_front(*i);
}
}
template <typename BaseList>
template <class... Args>
auto FrontModifyingListMixin<BaseList>::emplacePrepend(Args&&... args) -> reference {
Base::emplace_front(forward<Args>(args)...);
return *Base::begin();
}
template <typename BaseList>
void FrontModifyingListMixin<BaseList>::removeFirst() {
if (Base::empty())
throw OutOfRangeException("removeFirst() called on empty list");
Base::pop_front();
}
template <typename BaseList>
auto FrontModifyingListMixin<BaseList>::takeFirst() -> value_type {
value_type e = std::move(Base::first());
Base::pop_front();
return e;
}
template <typename BaseList>
void FrontModifyingListMixin<BaseList>::limitSizeFront(size_t maximumSize) {
while (Base::size() > maximumSize)
Base::pop_front();
}
template <typename Element, typename Allocator>
template <typename Container>
List<Element, Allocator> List<Element, Allocator>::from(Container const& c) {
return List(c.begin(), c.end());
}
template <typename Element, typename Allocator>
auto List<Element, Allocator>::ptr() -> value_type * {
return Base::data();
}
template <typename Element, typename Allocator>
auto List<Element, Allocator>::ptr() const -> value_type const * {
return Base::data();
}
template <typename Element, typename Allocator>
auto List<Element, Allocator>::slice(SliceIndex a, SliceIndex b, int i) const -> List {
return Star::slice(*this, a, b, i);
}
template <typename Element, typename Allocator>
template <typename Filter>
auto List<Element, Allocator>::filtered(Filter&& filter) const -> List {
List list(*this);
list.filter(forward<Filter>(filter));
return list;
}
template <typename Element, typename Allocator>
template <typename Comparator>
auto List<Element, Allocator>::sorted(Comparator&& comparator) const -> List {
List list(*this);
list.sort(forward<Comparator>(comparator));
return list;
}
template <typename Element, typename Allocator>
List<Element, Allocator> List<Element, Allocator>::sorted() const {
List list(*this);
list.sort();
return list;
}
template <typename Element, typename Allocator>
template <typename Function>
auto List<Element, Allocator>::transformed(Function&& function) {
List<typename std::decay<decltype(std::declval<Function>()(std::declval<reference>()))>::type> res;
res.reserve(Base::size());
transformInto(res, *this, forward<Function>(function));
return res;
}
template <typename Element, typename Allocator>
template <typename Function>
auto List<Element, Allocator>::transformed(Function&& function) const {
List<typename std::decay<decltype(std::declval<Function>()(std::declval<const_reference>()))>::type> res;
res.reserve(Base::size());
transformInto(res, *this, forward<Function>(function));
return res;
}
template <typename Element, size_t MaxSize>
template <typename Container>
StaticList<Element, MaxSize> StaticList<Element, MaxSize>::from(Container const& c) {
return StaticList(c.begin(), c.end());
}
template <typename Element, size_t MaxSize>
auto StaticList<Element, MaxSize>::slice(SliceIndex a, SliceIndex b, int i) const -> StaticList {
return Star::slice(*this, a, b, i);
}
template <typename Element, size_t MaxSize>
template <typename Filter>
auto StaticList<Element, MaxSize>::filtered(Filter&& filter) const -> StaticList {
StaticList list(*this);
list.filter(forward<Filter>(filter));
return list;
}
template <typename Element, size_t MaxSize>
template <typename Comparator>
auto StaticList<Element, MaxSize>::sorted(Comparator&& comparator) const -> StaticList {
StaticList list(*this);
list.sort(forward<Comparator>(comparator));
return list;
}
template <typename Element, size_t MaxSize>
StaticList<Element, MaxSize> StaticList<Element, MaxSize>::sorted() const {
StaticList list(*this);
list.sort();
return list;
}
template <typename Element, size_t MaxSize>
template <typename Function>
auto StaticList<Element, MaxSize>::transformed(Function&& function) {
StaticList<typename std::decay<decltype(std::declval<Function>()(std::declval<reference>()))>::type, MaxSize> res;
transformInto(res, *this, forward<Function>(function));
return res;
}
template <typename Element, size_t MaxSize>
template <typename Function>
auto StaticList<Element, MaxSize>::transformed(Function&& function) const {
StaticList<typename std::decay<decltype(std::declval<Function>()(std::declval<const_reference>()))>::type, MaxSize> res;
transformInto(res, *this, forward<Function>(function));
return res;
}
template <typename Element, size_t MaxStackSize>
template <typename Container>
SmallList<Element, MaxStackSize> SmallList<Element, MaxStackSize>::from(Container const& c) {
return SmallList(c.begin(), c.end());
}
template <typename Element, size_t MaxStackSize>
auto SmallList<Element, MaxStackSize>::slice(SliceIndex a, SliceIndex b, int i) const -> SmallList {
return Star::slice(*this, a, b, i);
}
template <typename Element, size_t MaxStackSize>
template <typename Filter>
auto SmallList<Element, MaxStackSize>::filtered(Filter&& filter) const -> SmallList {
SmallList list(*this);
list.filter(forward<Filter>(filter));
return list;
}
template <typename Element, size_t MaxStackSize>
template <typename Comparator>
auto SmallList<Element, MaxStackSize>::sorted(Comparator&& comparator) const -> SmallList {
SmallList list(*this);
list.sort(forward<Comparator>(comparator));
return list;
}
template <typename Element, size_t MaxStackSize>
SmallList<Element, MaxStackSize> SmallList<Element, MaxStackSize>::sorted() const {
SmallList list(*this);
list.sort();
return list;
}
template <typename Element, size_t MaxStackSize>
template <typename Function>
auto SmallList<Element, MaxStackSize>::transformed(Function&& function) {
SmallList<typename std::decay<decltype(std::declval<Function>()(std::declval<reference>()))>::type, MaxStackSize> res;
transformInto(res, *this, forward<Function>(function));
return res;
}
template <typename Element, size_t MaxStackSize>
template <typename Function>
auto SmallList<Element, MaxStackSize>::transformed(Function&& function) const {
SmallList<typename std::decay<decltype(std::declval<Function>()(std::declval<const_reference>()))>::type, MaxStackSize> res;
transformInto(res, *this, forward<Function>(function));
return res;
}
template <typename Element, typename Allocator>
template <typename Container>
Deque<Element, Allocator> Deque<Element, Allocator>::from(Container const& c) {
return Deque(c.begin(), c.end());
}
template <typename Element, typename Allocator>
Deque<Element, Allocator> Deque<Element, Allocator>::slice(SliceIndex a, SliceIndex b, int i) const {
return Star::slice(*this, a, b, i);
}
template <typename Element, typename Allocator>
template <typename Filter>
Deque<Element, Allocator> Deque<Element, Allocator>::filtered(Filter&& filter) const {
Deque l(*this);
l.filter(forward<Filter>(filter));
return l;
}
template <typename Element, typename Allocator>
template <typename Comparator>
Deque<Element, Allocator> Deque<Element, Allocator>::sorted(Comparator&& comparator) const {
Deque l(*this);
l.sort(forward<Comparator>(comparator));
return l;
}
template <typename Element, typename Allocator>
Deque<Element, Allocator> Deque<Element, Allocator>::sorted() const {
Deque l(*this);
l.sort();
return l;
}
template <typename Element, typename Allocator>
template <typename Function>
auto Deque<Element, Allocator>::transformed(Function&& function) {
return Star::transform<Deque<decltype(std::declval<Function>()(std::declval<reference>()))>>(*this, forward<Function>(function));
}
template <typename Element, typename Allocator>
template <typename Function>
auto Deque<Element, Allocator>::transformed(Function&& function) const {
return Star::transform<Deque<decltype(std::declval<Function>()(std::declval<const_reference>()))>>(*this, forward<Function>(function));
}
template <typename Element, typename Allocator>
template <typename Container>
LinkedList<Element, Allocator> LinkedList<Element, Allocator>::from(Container const& c) {
return LinkedList(c.begin(), c.end());
}
template <typename Element, typename Allocator>
void LinkedList<Element, Allocator>::appendAll(LinkedList list) {
Base::splice(Base::end(), list);
}
template <typename Element, typename Allocator>
void LinkedList<Element, Allocator>::prependAll(LinkedList list) {
Base::splice(Base::begin(), list);
}
template <typename Element, typename Allocator>
template <typename Container>
void LinkedList<Element, Allocator>::appendAll(Container&& list) {
for (auto& e : list) {
if (std::is_rvalue_reference<Container&&>::value)
Base::push_back(std::move(e));
else
Base::push_back(e);
}
}
template <typename Element, typename Allocator>
template <typename Container>
void LinkedList<Element, Allocator>::prependAll(Container&& list) {
for (auto i = std::rbegin(list); i != std::rend(list); ++i) {
if (std::is_rvalue_reference<Container&&>::value)
Base::push_front(std::move(*i));
else
Base::push_front(*i);
}
}
template <typename Element, typename Allocator>
template <typename Filter>
LinkedList<Element, Allocator> LinkedList<Element, Allocator>::filtered(Filter&& filter) const {
LinkedList list(*this);
list.filter(forward<Filter>(filter));
return list;
}
template <typename Element, typename Allocator>
template <typename Comparator>
LinkedList<Element, Allocator> LinkedList<Element, Allocator>::sorted(Comparator&& comparator) const {
LinkedList l(*this);
l.sort(forward<Comparator>(comparator));
return l;
}
template <typename Element, typename Allocator>
LinkedList<Element, Allocator> LinkedList<Element, Allocator>::sorted() const {
LinkedList l(*this);
l.sort();
return l;
}
template <typename Element, typename Allocator>
template <typename Function>
auto LinkedList<Element, Allocator>::transformed(Function&& function) {
return Star::transform<LinkedList<decltype(std::declval<Function>()(std::declval<reference>()))>>(*this, forward<Function>(function));
}
template <typename Element, typename Allocator>
template <typename Function>
auto LinkedList<Element, Allocator>::transformed(Function&& function) const {
return Star::transform<LinkedList<decltype(std::declval<Function>()(std::declval<const_reference>()))>>(*this, forward<Function>(function));
}
template <typename BaseList>
std::ostream& operator<<(std::ostream& os, ListMixin<BaseList> const& list) {
os << "(";
for (auto i = list.begin(); i != list.end(); ++i) {
if (i != list.begin())
os << ", ";
os << *i;
}
os << ")";
return os;
}
template <typename List>
size_t ListHasher<List>::operator()(List const& l) const {
size_t h = 0;
for (auto const& e : l)
hashCombine(h, elemHasher(e));
return h;
}
template <typename... Containers>
typename ListZipTypes<Containers...>::Result zip(Containers&&... args) {
typename ListZipTypes<Containers...>::Result res;
for (auto el : zipIterator(args...))
res.push_back(std::move(el));
return res;
}
template <typename Container>
typename ListEnumerateTypes<Container>::Result enumerate(Container&& container) {
typename ListEnumerateTypes<Container>::Result res;
for (auto el : enumerateIterator(container))
res.push_back(std::move(el));
return res;
}
}
template <typename BaseList>
struct fmt::formatter<Star::ListMixin<BaseList>> : ostream_formatter {};
#endif