LCOV - code coverage report
Current view: top level - src/immer/detail - iterator_facade.hpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 14 14 100.0 %
Date: 2025-02-23 09:33:43 Functions: 0 0 -

          Line data    Source code
       1             : //
       2             : // immer: immutable data structures for C++
       3             : // Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
       4             : //
       5             : // This software is distributed under the Boost Software License, Version 1.0.
       6             : // See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
       7             : //
       8             : 
       9             : #pragma once
      10             : 
      11             : #include <cstddef>
      12             : #include <iterator>
      13             : #include <type_traits>
      14             : 
      15             : namespace immer {
      16             : namespace detail {
      17             : 
      18             : struct iterator_core_access
      19             : {
      20             :     template <typename T>
      21      350173 :     static decltype(auto) dereference(T&& x)
      22             :     {
      23      350173 :         return x.dereference();
      24             :     }
      25             : 
      26             :     template <typename T>
      27      350082 :     static decltype(auto) increment(T&& x)
      28             :     {
      29      350082 :         return x.increment();
      30             :     }
      31             : 
      32             :     template <typename T>
      33             :     static decltype(auto) decrement(T&& x)
      34             :     {
      35             :         return x.decrement();
      36             :     }
      37             : 
      38             :     template <typename T1, typename T2>
      39      429438 :     static decltype(auto) equal(T1&& x1, T2&& x2)
      40             :     {
      41      429438 :         return x1.equal(x2);
      42             :     }
      43             : 
      44             :     template <typename T, typename D>
      45             :     static decltype(auto) advance(T&& x, D d)
      46             :     {
      47             :         return x.advance(d);
      48             :     }
      49             : 
      50             :     template <typename T1, typename T2>
      51             :     static decltype(auto) distance_to(T1&& x1, T2&& x2)
      52             :     {
      53             :         return x1.distance_to(x2);
      54             :     }
      55             : };
      56             : 
      57             : /*!
      58             :  * Minimalistic reimplementation of boost::iterator_facade
      59             :  */
      60             : template <typename DerivedT,
      61             :           typename IteratorCategoryT,
      62             :           typename T,
      63             :           typename ReferenceT      = T&,
      64             :           typename DifferenceTypeT = std::ptrdiff_t,
      65             :           typename PointerT        = T*>
      66             : class iterator_facade
      67             : {
      68             : public:
      69             :     using iterator_category = IteratorCategoryT;
      70             :     using value_type        = T;
      71             :     using difference_type   = DifferenceTypeT;
      72             :     using pointer           = PointerT;
      73             :     using reference         = ReferenceT;
      74             : 
      75             : protected:
      76             :     using access_t = iterator_core_access;
      77             : 
      78             :     constexpr static auto is_random_access =
      79             :         std::is_base_of<std::random_access_iterator_tag,
      80             :                         IteratorCategoryT>::value;
      81             :     constexpr static auto is_bidirectional =
      82             :         std::is_base_of<std::bidirectional_iterator_tag,
      83             :                         IteratorCategoryT>::value;
      84             : 
      85             :     class reference_proxy
      86             :     {
      87             :         friend iterator_facade;
      88             :         DerivedT iter_;
      89             : 
      90             :         reference_proxy(DerivedT iter)
      91             :             : iter_{std::move(iter)}
      92             :         {}
      93             : 
      94             :     public:
      95             :         operator ReferenceT() const { return *iter_; }
      96             :     };
      97             : 
      98      350173 :     const DerivedT& derived() const
      99             :     {
     100             :         static_assert(std::is_base_of<iterator_facade, DerivedT>::value,
     101             :                       "must pass a derived thing");
     102             :         return *static_cast<const DerivedT*>(this);
     103             :     }
     104      350082 :     DerivedT& derived()
     105             :     {
     106             :         static_assert(std::is_base_of<iterator_facade, DerivedT>::value,
     107             :                       "must pass a derived thing");
     108             :         return *static_cast<DerivedT*>(this);
     109             :     }
     110             : 
     111             : public:
     112      350173 :     ReferenceT operator*() const { return access_t::dereference(derived()); }
     113             :     PointerT operator->() const { return &access_t::dereference(derived()); }
     114             :     reference_proxy operator[](DifferenceTypeT n) const
     115             :     {
     116             :         static_assert(is_random_access, "");
     117             :         return derived() + n;
     118             :     }
     119             : 
     120             :     friend bool operator==(const DerivedT& a, const DerivedT& b)
     121             :     {
     122             :         return access_t::equal(a, b);
     123             :     }
     124      429438 :     friend bool operator!=(const DerivedT& a, const DerivedT& b)
     125             :     {
     126      429438 :         return !access_t::equal(a, b);
     127             :     }
     128             : 
     129      350082 :     DerivedT& operator++()
     130             :     {
     131      350082 :         access_t::increment(derived());
     132      350082 :         return derived();
     133             :     }
     134             :     DerivedT operator++(int)
     135             :     {
     136             :         auto tmp = derived();
     137             :         access_t::increment(derived());
     138             :         return tmp;
     139             :     }
     140             : 
     141             :     DerivedT& operator--()
     142             :     {
     143             :         static_assert(is_bidirectional || is_random_access, "");
     144             :         access_t::decrement(derived());
     145             :         return derived();
     146             :     }
     147             :     DerivedT operator--(int)
     148             :     {
     149             :         static_assert(is_bidirectional || is_random_access, "");
     150             :         auto tmp = derived();
     151             :         access_t::decrement(derived());
     152             :         return tmp;
     153             :     }
     154             : 
     155             :     DerivedT& operator+=(DifferenceTypeT n)
     156             :     {
     157             :         access_t::advance(derived(), n);
     158             :         return derived();
     159             :     }
     160             :     DerivedT& operator-=(DifferenceTypeT n)
     161             :     {
     162             :         access_t::advance(derived(), -n);
     163             :         return derived();
     164             :     }
     165             : 
     166             :     DerivedT operator+(DifferenceTypeT n) const
     167             :     {
     168             :         static_assert(is_random_access, "");
     169             :         auto tmp = derived();
     170             :         return tmp += n;
     171             :     }
     172             :     friend DerivedT operator+(DifferenceTypeT n, const DerivedT& i)
     173             :     {
     174             :         static_assert(is_random_access, "");
     175             :         return i + n;
     176             :     }
     177             :     DerivedT operator-(DifferenceTypeT n) const
     178             :     {
     179             :         static_assert(is_random_access, "");
     180             :         auto tmp = derived();
     181             :         return tmp -= n;
     182             :     }
     183             :     friend DifferenceTypeT operator-(const DerivedT& a, const DerivedT& b)
     184             :     {
     185             :         static_assert(is_random_access, "");
     186             :         return access_t::distance_to(b, a);
     187             :     }
     188             : 
     189             :     friend bool operator<(const DerivedT& a, const DerivedT& b)
     190             :     {
     191             :         static_assert(is_random_access, "");
     192             :         return access_t::distance_to(a, b) > 0;
     193             :     }
     194             :     friend bool operator<=(const DerivedT& a, const DerivedT& b)
     195             :     {
     196             :         static_assert(is_random_access, "");
     197             :         return access_t::distance_to(a, b) >= 0;
     198             :     }
     199             :     friend bool operator>(const DerivedT& a, const DerivedT& b)
     200             :     {
     201             :         static_assert(is_random_access, "");
     202             :         return access_t::distance_to(a, b) < 0;
     203             :     }
     204             :     friend bool operator>=(const DerivedT& a, const DerivedT& b)
     205             :     {
     206             :         static_assert(is_random_access, "");
     207             :         return access_t::distance_to(a, b) <= 0;
     208             :     }
     209             : };
     210             : 
     211             : } // namespace detail
     212             : } // namespace immer

Generated by: LCOV version 1.14