7#include "../sources/ContainerSources.h"
8#include "../util/TraitImpl.h"
17 template<
typename TChainInput>
18 class [[nodiscard(CXXITER_CHAINER_NODISCARD_WARNING)]] Reverse :
public IterApi<Reverse<TChainInput>> {
19 friend struct trait::Iterator<Reverse<TChainInput>>;
20 friend struct trait::DoubleEndedIterator<Reverse<TChainInput>>;
21 friend struct trait::ExactSizeIterator<Reverse<TChainInput>>;
23 using InputItem =
typename TChainInput::Item;
25 struct NoReverseCache {};
26 using ReverseCacheContainer = std::conditional_t<
27 std::is_reference_v<InputItem>,
28 std::vector<std::reference_wrapper<InputItem>>,
29 std::vector<InputItem>>;
30 using ReverseCache = SrcMov<ReverseCacheContainer>;
34 static constexpr bool USE_CACHE = !CXXIterDoubleEndedIterator<TChainInput>;
36 std::conditional_t<USE_CACHE, std::optional<ReverseCache>, NoReverseCache> reverseCache;
39 constexpr Reverse(TChainInput&& input) : input(std::move(input)) {}
44 template<
typename TChainInput>
45 struct trait::Iterator<op::Reverse<TChainInput>> {
46 using ChainInputIterator = trait::Iterator<TChainInput>;
47 using InputItem =
typename TChainInput::Item;
49 using Self = op::Reverse<TChainInput>;
50 using Item = InputItem;
52 static void initReverseCache(Self& self) {
54 typename Self::ReverseCacheContainer reverseCache;
55 reverseCache.reserve(self.input.sizeHint().expectedResultSize());
57 auto item = ChainInputIterator::next(self.input);
58 if(!item.has_value()) {
break; }
59 reverseCache.push_back(std::move(item.value()));
61 self.reverseCache =
typename Self::ReverseCache(std::move(reverseCache));
64 static constexpr inline IterValue<Item> next(Self& self) {
65 if constexpr(Self::USE_CACHE) {
66 if(!self.reverseCache.has_value()) [[unlikely]] { initReverseCache(self); }
67 return trait::DoubleEndedIterator<typename Self::ReverseCache>::nextBack(self.reverseCache.value());
69 return trait::DoubleEndedIterator<TChainInput>::nextBack(self.input);
72 static constexpr inline SizeHint sizeHint(
const Self& self) {
return ChainInputIterator::sizeHint(self.input); }
73 static constexpr inline size_t advanceBy(Self& self,
size_t n) {
return util::advanceByPullBack(self, n); }
76 template<CXXIterDoubleEndedIterator TChainInput>
77 struct trait::DoubleEndedIterator<op::Reverse<TChainInput>> {
78 using ChainInputIterator = trait::Iterator<TChainInput>;
79 using InputItem =
typename TChainInput::Item;
81 using Self = op::Reverse<TChainInput>;
82 using Item = InputItem;
84 static constexpr inline IterValue<Item> nextBack(Self& self) {
85 if constexpr(Self::USE_CACHE) {
86 if(!self.reverseCache.has_value()) [[unlikely]] { initReverseCache(self); }
87 return trait::Iterator<typename Self::ReverseCache>::next(self.reverseCache.value());
89 return ChainInputIterator::next(self.input);
94 template<CXXIterExactSizeIterator TChainInput>
95 struct trait::ExactSizeIterator<op::Reverse<TChainInput>> {
96 static constexpr inline size_t size(
const op::Reverse<TChainInput>& self) {
97 return trait::ExactSizeIterator<TChainInput>::size(self.input);