Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #pragma once 11 : 12 : #include <iterator> 13 : #include <iostream> 14 : 15 : namespace Moose 16 : { 17 : // Forward Declarations of helper objects 18 : template <class Iterator> 19 : struct _enumerate_struct; 20 : 21 : template <class Iterator> 22 : struct _enumerate_iterator; 23 : 24 : template <class Iterator> 25 : struct _enumerate_range; 26 : 27 : /** 28 : * Enumerate function for iterating over a range and obtaining both a reference to the underlying 29 : * type and an index simultaneously. This method is forward-compatible with the C++17 structured 30 : * bindings capability. 31 : * 32 : * C++11 compatible usage: 33 : * 34 : * for (auto it : Moose::enumerate(values)) 35 : * _console << it.index() << ": " << it.value() << '\n'; 36 : * 37 : * // Here the third argument is the starting index value 38 : * for (auto it : Moose::enumerate(values.begin(), values.end(), 0)) 39 : * _console << it.index() << ": " << it.value() << '\n'; 40 : * 41 : * C++17 usage (DO NOT USE IN MOOSE): 42 : * 43 : * for (auto [index, value] : Moose::enumerate(values)) 44 : * _console << index << ": " << value << '\n'; 45 : * 46 : * // Here the third argument is the starting index value 47 : * for (auto [index, value] : Moose::enumerate(values.begin(), values.end(), 0)) 48 : * _console << index << ": " << value << '\n'; 49 : */ 50 : template <class Iterator> 51 : _enumerate_range<Iterator> 52 1 : enumerate(Iterator first, 53 : Iterator last, 54 : typename std::iterator_traits<Iterator>::difference_type initial) 55 : { 56 1 : return _enumerate_range<Iterator>(first, last, initial); 57 : } 58 : 59 : template <class Container> 60 : _enumerate_range<typename Container::iterator> 61 1399 : enumerate(Container & content) 62 : { 63 1399 : return _enumerate_range<typename Container::iterator>(std::begin(content), std::end(content), 0); 64 : } 65 : 66 : template <class Container> 67 : _enumerate_range<typename Container::const_iterator> 68 2155809 : enumerate(const Container & content) 69 : { 70 : return _enumerate_range<typename Container::const_iterator>( 71 2155809 : std::begin(content), std::end(content), 0); 72 : } 73 : 74 : ////////////////////////////////////////////////////////////////////////////////////////////////// 75 : // Helper object 76 : template <class Iterator> 77 : struct _enumerate_struct 78 : { 79 : using iterator = Iterator; 80 : using index_type = typename std::iterator_traits<iterator>::difference_type; 81 : using reference = typename std::iterator_traits<iterator>::reference; 82 : 83 6904554 : _enumerate_struct(index_type index, iterator iterator) : l_index(index), l_iter(iterator) {} 84 : 85 4028858 : index_type index() { return l_index; } 86 : 87 6906124 : reference value() { return *l_iter; } 88 : 89 : private: 90 : index_type l_index; 91 : iterator l_iter; 92 : }; 93 : 94 : // Helper object 95 : template <class Iterator> 96 : struct _enumerate_iterator 97 : { 98 : using iterator = Iterator; 99 : using index_type = typename std::iterator_traits<iterator>::difference_type; 100 : using reference = typename std::iterator_traits<iterator>::reference; 101 : 102 4314418 : _enumerate_iterator(index_type index, iterator iterator) : index(index), iter(iterator) {} 103 : 104 6904554 : _enumerate_iterator & operator++() 105 : { 106 6904554 : ++index; 107 6904554 : ++iter; 108 6904554 : return *this; 109 : } 110 : 111 9061763 : bool operator!=(const _enumerate_iterator & other) const { return iter != other.iter; } 112 : 113 : /** 114 : * When MOOSE moves to C++17, we'll switch the return type of the dereference operator and the 115 : * corresponding calling code. This is what 116 : * we'll use instead. 117 : * 118 : * #if __cplusplus > 201402L 119 : * std::pair<index_type &, reference> operator*() { return {index, *iter}; } 120 : * #endif 121 : */ 122 6904554 : _enumerate_struct<iterator> operator*() { return _enumerate_struct<iterator>(index, iter); } 123 : 124 : private: 125 : index_type index; 126 : iterator iter; 127 : }; 128 : 129 : template <class Iterator> 130 : struct _enumerate_range 131 : { 132 : using index_type = typename std::iterator_traits<Iterator>::difference_type; 133 : using iterator = _enumerate_iterator<Iterator>; 134 : 135 2157209 : _enumerate_range(Iterator first, Iterator last, index_type initial) 136 2157209 : : first(first), last(last), initial(initial) 137 : { 138 2157209 : } 139 : 140 2157209 : iterator begin() const { return iterator(initial, first); } 141 : 142 2157209 : iterator end() const { return iterator(0, last); } 143 : 144 : private: 145 : Iterator first; 146 : Iterator last; 147 : index_type initial; 148 : }; 149 : }