CXXIter 0.2
Loading...
Searching...
No Matches
Unique.h
1#pragma once
2
3#include <unordered_set>
4
5#include "../Common.h"
6#include "../sources/ContainerSources.h"
7#include "../util/TraitImpl.h"
8
9namespace CXXIter {
10
11 // ################################################################################################
12 // UNIQUE
13 // ################################################################################################
14 namespace op {
16 template<typename TChainInput, typename TMapFn>
17 class [[nodiscard(CXXITER_CHAINER_NODISCARD_WARNING)]] Unique : public IterApi<Unique<TChainInput, TMapFn>> {
18 friend struct trait::Iterator<Unique<TChainInput, TMapFn>>;
19 private:
20 using OwnedInputItem = typename TChainInput::ItemOwned;
21
22 TChainInput input;
23 TMapFn mapFn;
24 std::unordered_set<OwnedInputItem> uniqueCache;
25 public:
26 constexpr Unique(TChainInput&& input, TMapFn mapFn) : input(std::move(input)), mapFn(mapFn) {
27 uniqueCache.reserve(this->input.sizeHint().expectedResultSize());
28 }
29 };
30 }
31 // ------------------------------------------------------------------------------------------------
33 template<typename TChainInput, typename TMapFn>
34 struct trait::Iterator<op::Unique<TChainInput, TMapFn>> {
35 using ChainInputIterator = trait::Iterator<TChainInput>;
36 using InputItem = typename TChainInput::Item;
37 using OwnedInputItem = typename TChainInput::ItemOwned;
38 // CXXIter Interface
39 using Self = op::Unique<TChainInput, TMapFn>;
40 using Item = InputItem;
41
42 static constexpr inline IterValue<Item> next(Self& self) {
43 while(true) {
44 auto item = ChainInputIterator::next(self.input);
45 if(!item.has_value()) [[unlikely]] { return {}; } // reached end of input
46
47 auto itemUniqueValue = self.mapFn(item.value());
48 if(self.uniqueCache.contains(itemUniqueValue)) { continue; } // uniqueness-property violated, ignore item
49 self.uniqueCache.insert(std::move(itemUniqueValue));
50 return item;
51 }
52 }
53 static constexpr inline SizeHint sizeHint(const Self& self) {
54 SizeHint input = ChainInputIterator::sizeHint(self.input);
55 return SizeHint(0, input.upperBound);
56 }
57 static constexpr inline size_t advanceBy(Self& self, size_t n) { return util::advanceByPull(self, n); }
58 };
59
60}
CXXIter.
Definition: CXXIter.h:48