3#include <unordered_set>
6#include "../sources/ContainerSources.h"
7#include "../util/TraitImpl.h"
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>>;
20 using OwnedInputItem =
typename TChainInput::ItemOwned;
24 std::unordered_set<OwnedInputItem> uniqueCache;
26 constexpr Unique(TChainInput&& input, TMapFn mapFn) : input(std::move(input)), mapFn(mapFn) {
27 uniqueCache.reserve(this->input.sizeHint().expectedResultSize());
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;
39 using Self = op::Unique<TChainInput, TMapFn>;
40 using Item = InputItem;
42 static constexpr inline IterValue<Item> next(Self& self) {
44 auto item = ChainInputIterator::next(self.input);
45 if(!item.has_value()) [[unlikely]] {
return {}; }
47 auto itemUniqueValue = self.mapFn(item.value());
48 if(self.uniqueCache.contains(itemUniqueValue)) {
continue; }
49 self.uniqueCache.insert(std::move(itemUniqueValue));
53 static constexpr inline SizeHint sizeHint(
const Self& self) {
54 SizeHint input = ChainInputIterator::sizeHint(self.input);
55 return SizeHint(0, input.upperBound);
57 static constexpr inline size_t advanceBy(Self& self,
size_t n) {
return util::advanceByPull(self, n); }