LCOV - code coverage report
Current view: top level - include/utils - Enumerate.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 21 21 100.0 %
Date: 2025-07-17 01:28:37 Functions: 55 55 100.0 %
Legend: Lines: hit not hit

          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             : }

Generated by: LCOV version 1.14