15 template<
typename TChainInput1,
typename TChainInput2>
16 class [[nodiscard(CXXITER_CHAINER_NODISCARD_WARNING)]] Chainer :
public IterApi<Chainer<TChainInput1, TChainInput2>> {
17 friend struct trait::Iterator<Chainer<TChainInput1, TChainInput2>>;
18 friend struct trait::DoubleEndedIterator<Chainer<TChainInput1, TChainInput2>>;
19 friend struct trait::ExactSizeIterator<Chainer<TChainInput1, TChainInput2>>;
23 bool input1Ended =
false;
24 bool input2Ended =
false;
26 constexpr Chainer(TChainInput1&& input1, TChainInput2 input2) : input1(std::move(input1)), input2(std::move(input2)) {}
31 template<
typename TChainInput1,
typename TChainInput2>
32 struct trait::Iterator<op::Chainer<TChainInput1, TChainInput2>> {
33 using ChainInputIterator1 = trait::Iterator<TChainInput1>;
34 using ChainInputIterator2 = trait::Iterator<TChainInput2>;
35 using InputItem =
typename trait::Iterator<TChainInput1>::Item;
37 using Self = op::Chainer<TChainInput1, TChainInput2>;
38 using Item = InputItem;
40 static constexpr inline IterValue<Item> next(Self& self) {
42 if(self.input1Ended ==
false) {
43 auto item = ChainInputIterator1::next(self.input1);
44 if(!item.has_value()) [[unlikely]] {
45 self.input1Ended =
true;
50 auto item = ChainInputIterator2::next(self.input2);
51 if(!item.has_value()) [[unlikely]] { self.input2Ended =
true; }
56 static constexpr inline SizeHint sizeHint(
const Self& self) {
57 SizeHint result = ChainInputIterator1::sizeHint(self.input1);
58 result.add(ChainInputIterator2::sizeHint(self.input2));
61 static constexpr inline size_t advanceBy(Self& self,
size_t n) {
63 if(!self.input1Ended) {
64 skipped += ChainInputIterator1::advanceBy(self.input1, n);
66 if(!self.input2Ended) {
67 skipped += ChainInputIterator2::advanceBy(self.input2, (n - skipped));
73 template<CXXIterDoubleEndedIterator TChainInput1, CXXIterDoubleEndedIterator TChainInput2>
74 struct trait::DoubleEndedIterator<op::Chainer<TChainInput1, TChainInput2>> {
75 using ChainInputIterator1 = trait::DoubleEndedIterator<TChainInput1>;
76 using ChainInputIterator2 = trait::DoubleEndedIterator<TChainInput2>;
77 using InputItem =
typename trait::Iterator<TChainInput1>::Item;
79 using Self = op::Chainer<TChainInput1, TChainInput2>;
80 using Item = InputItem;
82 static constexpr inline IterValue<Item> nextBack(Self& self) {
84 if(self.input2Ended ==
false) {
85 auto item = ChainInputIterator2::nextBack(self.input2);
86 if(!item.has_value()) [[unlikely]] {
87 self.input2Ended =
true;
92 auto item = ChainInputIterator1::nextBack(self.input1);
93 if(!item.has_value()) [[unlikely]] { self.input1Ended =
true; }
100 template<CXXIterExactSizeIterator TChainInput1, CXXIterExactSizeIterator TChainInput2>
101 struct trait::ExactSizeIterator<op::Chainer<TChainInput1, TChainInput2>> {
102 static constexpr inline size_t size(
const op::Chainer<TChainInput1, TChainInput2>& self) {
103 return trait::Iterator<op::Chainer<TChainInput1, TChainInput2>>::sizeHint(self).lowerBound;