1 /**
2  * This code is part of Qiskit.
3  *
4  * (C) Copyright IBM 2018, 2019.
5  *
6  * This code is licensed under the Apache License, Version 2.0. You may
7  * obtain a copy of this license in the LICENSE.txt file in the root directory
8  * of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
9  *
10  * Any modifications or derivative works of this code must retain this
11  * copyright notice, and modified files need to carry a notice indicating
12  * that they have been altered from the originals.
13  */
14 
15 #ifndef _ITERATORS_HPP
16 #define _ITERATORS_HPP
17 
18 template <typename T>
19 struct iterator_extractor { using type = typename T::iterator; };
20 
21 template <typename T>
22 struct iterator_extractor<T const> { using type = typename T::const_iterator; };
23 
24 /**
25  * Python-like `enumerate()` for C++14 ranged-for
26  *
27  * I wish I'd had this included in the STL :)
28  *
29  * Usage:
30  * ```c++
31  * for(auto& elem: index(vec)){
32  *     std::cout << "Index: " << elem.first << " Element: " << elem.second;
33  * }
34  * ```
35  **/
36 template <typename T>
37 class Indexer {
38 public:
39     class _Iterator {
40         using inner_iterator =  typename iterator_extractor<T>::type;
41         using inner_reference = typename std::iterator_traits<inner_iterator>::reference;
42     public:
43         using reference = std::pair<size_t, inner_reference>;
44 
_Iterator(inner_iterator it)45         _Iterator(inner_iterator it): _pos(0), _it(it) {}
46 
operator *() const47         reference operator*() const {
48             return reference(_pos, *_it);
49         }
50 
operator ++()51         _Iterator& operator++() {
52             ++_pos;
53             ++_it;
54             return *this;
55         }
56 
operator ++(int)57         _Iterator operator++(int) {
58             _Iterator tmp(*this);
59             ++*this;
60             return tmp;
61         }
62 
operator ==(_Iterator const & it) const63         bool operator==(_Iterator const& it) const {
64             return _it == it._it;
65         }
operator !=(_Iterator const & it) const66         bool operator!=(_Iterator const& it) const {
67             return !(*this == it);
68         }
69 
70     private:
71         size_t _pos;
72         inner_iterator _it;
73     };
74 
Indexer(T & t)75     Indexer(T& t): _container(t) {}
76 
begin() const77     _Iterator begin() const {
78         return _Iterator(_container.begin());
79     }
end() const80     _Iterator end() const {
81         return _Iterator(_container.end());
82     }
83 
84 private:
85     T& _container;
86 }; // class Indexer
87 
88 template <typename T>
enumerate(T & t)89 Indexer<T> enumerate(T& t) { return Indexer<T>(t); }
90 
91 #endif