9#include "../util/TraitImpl.h"
13 template<
typename TItem, const
size_t CHUNK_SIZE>
14 using DynamicChunk = std::conditional_t<
15 std::is_reference_v<TItem>,
16 std::vector<std::reference_wrapper<TItem>>,
24 template<
typename TChainInput, const
size_t CHUNK_SIZE>
25 class [[nodiscard(CXXITER_CHAINER_NODISCARD_WARNING)]] Chunked :
public IterApi<Chunked<TChainInput, CHUNK_SIZE>> {
26 friend struct trait::Iterator<Chunked<TChainInput, CHUNK_SIZE>>;
27 friend struct trait::ExactSizeIterator<Chunked<TChainInput, CHUNK_SIZE>>;
30 bool reachedEnd =
false;
32 constexpr Chunked(TChainInput&& input) : input(std::move(input)) {}
37 template<
typename TChainInput, const
size_t CHUNK_SIZE>
38 struct trait::Iterator<op::Chunked<TChainInput, CHUNK_SIZE>> {
39 using ChainInputIterator = trait::Iterator<TChainInput>;
40 using InputItem =
typename TChainInput::Item;
42 using Self = op::Chunked<TChainInput, CHUNK_SIZE>;
43 using Item = DynamicChunk<InputItem, CHUNK_SIZE>;
45 static constexpr inline IterValue<Item> next(Self& self) {
46 if(self.reachedEnd) [[unlikely]] {
return {}; }
48 chunk.reserve(CHUNK_SIZE);
49 for(
size_t i = 0; i < CHUNK_SIZE; ++i) {
50 auto item = ChainInputIterator::next(self.input);
51 if(!item.has_value()) [[unlikely]] {
52 self.reachedEnd =
true;
53 if(chunk.size() == 0) {
return {}; }
56 chunk.push_back(std::move( item.value() ));
60 static constexpr inline SizeHint sizeHint(
const Self& self) {
61 SizeHint result = ChainInputIterator::sizeHint(self.input);
62 result.lowerBound = (result.lowerBound / CHUNK_SIZE) + (result.lowerBound % CHUNK_SIZE == 0 ? 0 : 1);
63 if(result.upperBound.has_value()) {
64 result.upperBound.value() = (result.upperBound.value() / CHUNK_SIZE) + (result.upperBound.value() % CHUNK_SIZE == 0 ? 0 : 1);
68 static constexpr inline size_t advanceBy(Self& self,
size_t n) {
return util::advanceByPull(self, n); }
71 template<CXXIterExactSizeIterator TChainInput, const
size_t CHUNK_SIZE>
72 struct trait::ExactSizeIterator<op::Chunked<TChainInput, CHUNK_SIZE>> {
73 static constexpr inline size_t size(
const op::Chunked<TChainInput, CHUNK_SIZE>& self) {
74 return trait::ExactSizeIterator<TChainInput>::size(self.input) / CHUNK_SIZE;