| 4198 | |
| 4199 | template <typename T> |
| 4200 | class RepeatGenerator : public IGenerator<T> { |
| 4201 | static_assert(!std::is_same<T, bool>::value, |
| 4202 | "RepeatGenerator currently does not support bools" |
| 4203 | "because of std::vector<bool> specialization"); |
| 4204 | GeneratorWrapper<T> m_generator; |
| 4205 | mutable std::vector<T> m_returned; |
| 4206 | size_t m_target_repeats; |
| 4207 | size_t m_current_repeat = 0; |
| 4208 | size_t m_repeat_index = 0; |
| 4209 | public: |
| 4210 | RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator): |
| 4211 | m_generator(std::move(generator)), |
| 4212 | m_target_repeats(repeats) |
| 4213 | { |
| 4214 | assert(m_target_repeats > 0 && "Repeat generator must repeat at least once"); |
| 4215 | } |
| 4216 | |
| 4217 | T const& get() const override { |
| 4218 | if (m_current_repeat == 0) { |
| 4219 | m_returned.push_back(m_generator.get()); |
| 4220 | return m_returned.back(); |
| 4221 | } |
| 4222 | return m_returned[m_repeat_index]; |
| 4223 | } |
| 4224 | |
| 4225 | bool next() override { |
| 4226 | // There are 2 basic cases: |
| 4227 | // 1) We are still reading the generator |
| 4228 | // 2) We are reading our own cache |
| 4229 | |
| 4230 | // In the first case, we need to poke the underlying generator. |
| 4231 | // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache |
| 4232 | if (m_current_repeat == 0) { |
| 4233 | const auto success = m_generator.next(); |
| 4234 | if (!success) { |
| 4235 | ++m_current_repeat; |
| 4236 | } |
| 4237 | return m_current_repeat < m_target_repeats; |
| 4238 | } |
| 4239 | |
| 4240 | // In the second case, we need to move indices forward and check that we haven't run up against the end |
| 4241 | ++m_repeat_index; |
| 4242 | if (m_repeat_index == m_returned.size()) { |
| 4243 | m_repeat_index = 0; |
| 4244 | ++m_current_repeat; |
| 4245 | } |
| 4246 | return m_current_repeat < m_target_repeats; |
| 4247 | } |
| 4248 | }; |
| 4249 | |
| 4250 | template <typename T> |
| 4251 | GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) { |