3 * \remark This file is part of VITA.
5 * \copyright Copyright (C) 2015-2019 EOS di Manlio Morini.
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
10 * You can obtain one at http://mozilla.org/MPL/2.0/
13#if !defined(VITA_POPULATION_H)
14# error "Don't include this file directly, include the specific .h instead"
17#if !defined(VITA_POPULATION_ITERATOR_TCC)
18#define VITA_POPULATION_ITERATOR_TCC
21/// Iterator for a population.
23/// `population<T>::base_iterator` / `population<T>::begin()` /
24/// `population<T>::end()` are general and clear, so they should be the
25/// preferred way to scan / perform an action over every individual of a
29/// For performance critical code accessing individuals via the `operator[]`
30/// could give better results.
33template<bool is_const>
34class population<T>::base_iterator
37 using iterator_category = std::forward_iterator_tag;
39 using pointer = value_type *;
40 using const_pointer = const value_type *;
41 using reference = value_type &;
42 using const_reference = const value_type &;
44 using ptr = std::conditional_t<is_const, const_pointer, pointer>;
45 using ref = std::conditional_t<is_const, const_reference, reference>;
46 using pop = std::conditional_t<is_const, const population, population>;
48 /// \param[in] p a population
49 /// \param[in] begin `false` for the `end()` iterator
50 base_iterator(pop &p, bool begin)
51 : pop_(&p), layer_(begin ? 0 : p.layers()), index_(0)
55 /// Prefix increment operator.
56 /// \return iterator to the next individual
57 /// \warning Advancing past the `end()` iterator results in undefined
59 base_iterator &operator++()
61 if (++index_ >= pop_->individuals(layer_))
65 do // skipping empty layers
67 while (layer_ < pop_->layers() && !pop_->individuals(layer_));
70 assert((layer_ < pop_->layers() && index_ < pop_->individuals(layer_)) ||
71 (layer_ == pop_->layers() && index_ == 0));
76 /// Postfix increment operator.
77 /// \return iterator to the current individual
78 base_iterator operator++(int)
80 base_iterator tmp(*this);
85 /// \param[in] rhs second term of comparison
86 /// \return `true` if iterators point to correspondant individuals
87 bool operator==(const base_iterator &rhs) const
89 return pop_ == rhs.pop_ && layer_ == rhs.layer_ && index_ == rhs.index_;
92 bool operator!=(const base_iterator &rhs) const
94 return !(*this == rhs);
97 unsigned layer() const
102 /// \return reference to the current individual
103 ref operator*() const
105 return pop_->operator[]({layer_, index_});
108 /// \return pointer to the current individual
109 ptr operator->() const
114 friend std::ostream &operator<<(std::ostream &out, const base_iterator &i)
116 out << '[' << i.layer_ << ',' << i.index_ << ']';
121 std::conditional_t<is_const, const population *, population *> pop_;
127#endif // include guard