7#include "../sources/ContainerSources.h"
8#include "../util/TraitImpl.h"
17 template<
typename TChainInput,
typename TCompareFn,
bool STABLE>
18 class [[nodiscard(CXXITER_CHAINER_NODISCARD_WARNING)]] Sorter :
public IterApi<Sorter<TChainInput, TCompareFn, STABLE>> {
19 friend struct trait::Iterator<Sorter<TChainInput, TCompareFn, STABLE>>;
20 friend struct trait::DoubleEndedIterator<Sorter<TChainInput, TCompareFn, STABLE>>;
21 friend struct trait::ExactSizeIterator<Sorter<TChainInput, TCompareFn, STABLE>>;
23 using OwnedInputItem =
typename TChainInput::ItemOwned;
24 using SortCache = SrcMov<std::vector<OwnedInputItem>>;
28 std::optional<SortCache> sortCache;
30 constexpr Sorter(TChainInput&& input, TCompareFn compareFn) : input(std::move(input)), compareFn(compareFn) {}
35 template<
typename TChainInput,
typename TCompareFn,
bool STABLE>
36 struct trait::Iterator<op::Sorter<TChainInput, TCompareFn, STABLE>> {
37 using ChainInputIterator = trait::Iterator<TChainInput>;
38 using InputItem =
typename TChainInput::Item;
39 using OwnedInputItem =
typename TChainInput::ItemOwned;
41 using Self = op::Sorter<TChainInput, TCompareFn, STABLE>;
42 using Item = OwnedInputItem;
44 static constexpr inline void initSortCache(Self& self) {
46 std::vector<OwnedInputItem> sortCache;
48 auto item = ChainInputIterator::next(self.input);
49 if(!item.has_value()) [[unlikely]] {
break; }
50 sortCache.push_back(std::forward<InputItem>( item.value() ));
53 if constexpr(STABLE) {
54 std::stable_sort(sortCache.begin(), sortCache.end(), self.compareFn);
56 std::sort(sortCache.begin(), sortCache.end(), self.compareFn);
58 self.sortCache.emplace(std::move(sortCache));
61 static constexpr inline IterValue<Item> next(Self& self) {
62 if(!self.sortCache.has_value()) [[unlikely]] { initSortCache(self); }
64 using SortCacheIterator = trait::Iterator<typename Self::SortCache>;
65 typename Self::SortCache& sortedItems = self.sortCache.value();
66 return SortCacheIterator::next(sortedItems);
68 static constexpr inline SizeHint sizeHint(
const Self& self) {
return ChainInputIterator::sizeHint(self.input); }
69 static constexpr inline size_t advanceBy(Self& self,
size_t n) {
return util::advanceByPull(self, n); }
72 template<CXXIterDoubleEndedIterator TChainInput,
typename TCompareFn,
bool STABLE>
73 struct trait::DoubleEndedIterator<op::Sorter<TChainInput, TCompareFn, STABLE>> {
74 using ChainInputIterator = trait::Iterator<TChainInput>;
75 using InputItem =
typename TChainInput::Item;
76 using OwnedInputItem =
typename TChainInput::ItemOwned;
78 using Self = op::Sorter<TChainInput, TCompareFn, STABLE>;
79 using Item = OwnedInputItem;
81 static constexpr inline IterValue<Item> nextBack(Self& self) {
82 if(!self.sortCache.has_value()) [[unlikely]] { trait::Iterator<Self>::initSortCache(self); }
84 using SortCacheIterator = trait::DoubleEndedIterator<typename Self::SortCache>;
85 typename Self::SortCache& sortedItems = self.sortCache.value();
86 return SortCacheIterator::nextBack(sortedItems);
90 template<CXXIterExactSizeIterator TChainInput,
typename TCompareFn,
bool STABLE>
91 struct trait::ExactSizeIterator<op::Sorter<TChainInput, TCompareFn, STABLE>> {
92 static constexpr inline size_t size(
const op::Sorter<TChainInput, TCompareFn, STABLE>& self) {
93 return trait::ExactSizeIterator<TChainInput>::size(self.input);