kblib  0.2.3
General utilities library for modern C++
enumerate-contrib-cry.h
Go to the documentation of this file.
1 /* *****************************************************************************
2  * Copyright (c) 2020 Krystian Stasiowski
3  *
4  * This code adapted from code written by Krystian Stasiowski
5  * <sdkrystian@gmail.com>
6  *
7  * No specific license provisions were given, however permission was granted for
8  * me to include it in kblib.
9  *
10  * His code is much faster and cleaner than my magic_enumerate is. HOWEVER, it
11  * is fundamentally unable to detect the copying-nonconst-from-const case.
12  *
13  * My modifications are:
14  * - Change from [val, idx] to [idx, val] to match Python's enumerate()
15  * - Wrote documentation
16  * - Change name from value_and_index() to cry_enumerate()
17  * - Silenced Clang warnings about std::tuple_element specializations with
18  * mismatched tags.
19  * - Formatting
20  *
21  * All credit for everything else goes to Krystian.
22  *
23  * ****************************************************************************/
24 
25 #ifndef ENUMERATECONTRIB_H
26 #define ENUMERATECONTRIB_H
27 #include "tdecl.h"
28 
29 #include <memory>
30 #include <type_traits>
31 
32 #if KBLIB_USE_CXX17
33 
34 namespace kblib {
38 namespace detail_cry {
39  template <typename>
40  struct value_index_pair;
41 
42  template <std::size_t N, typename T, std::enable_if_t<N == 0>* = nullptr>
43  auto get(T&& t)
44  -> std::conditional_t<std::is_reference_v<T>, const std::size_t&,
45  const std::size_t> {
46  return t.index;
47  }
48 
49  template <std::size_t N, typename T, std::enable_if_t<N == 1>* = nullptr>
50  auto get(T&& t)
51  -> std::conditional_t<std::is_reference_v<T>,
52  typename std::remove_reference_t<T>::value_type&,
53  typename std::remove_reference_t<T>::value_type> {
54  // static_assert(std::is_reference_v<T>);
55  // static_assert(
56  // std::is_const_v<std::remove_reference_t<decltype(*t.iter)>>);
57  return *t.iter;
58  }
59 
60  template <typename Iterator>
62  using value_type
63  = std::remove_reference_t<decltype(*std::declval<Iterator&>())>;
64 
65  std::size_t index;
66  Iterator iter;
67  };
68 
69  template <typename Range, typename = void>
71  public:
72  using iterator_type = decltype(std::begin(std::declval<Range&>()));
73 
75  : range_begin_(std::begin(range))
76  , range_end_(std::end(range)) {}
77 
78  auto range_begin() -> iterator_type { return range_begin_; }
79 
80  auto range_end() -> iterator_type { return range_end_; }
81 
84  };
85 
86  template <typename Range>
88  Range, std::enable_if_t<not std::is_reference_v<Range>>> {
89  public:
90  using iterator_type = decltype(std::begin(std::declval<Range&>()));
91 
93  : range_(std::move(range)) {}
94 
95  auto range_begin() -> iterator_type { return std::begin(range_); }
96 
97  auto range_end() -> iterator_type { return std::end(range_); }
98 
99  Range range_;
100  };
101 
102  template <typename Range>
105 
107  : value_and_index_base<Range>(range)
108  , begin_(this->range_begin(), 0)
109  , end_(this->range_end(), 0) {}
110 
111  struct iterator {
112  private:
114 
115  public:
116  iterator(iterator_type iter, std::size_t index = 0)
117  : pair_{index, iter} {}
118 
119  auto operator*() -> value_index_pair<iterator_type>& { return pair_; }
120 
121  auto operator++(int) -> iterator {
122  iterator copy(pair_.iter, pair_.index);
123  ++pair_.iter, ++pair_.index;
124  return copy;
125  }
126 
127  auto operator++() -> iterator& {
128  ++pair_.iter, ++pair_.index;
129  return *this;
130  }
131 
132  auto operator==(const iterator& other) const -> bool {
133  return other.pair_.iter == pair_.iter;
134  }
135 
136  auto operator!=(const iterator& other) const -> bool {
137  return not (other == *this);
138  }
139  };
140 
141  auto begin() -> iterator { return begin_; }
142 
143  auto end() -> iterator { return end_; }
144 
145  private:
146  iterator begin_;
147  iterator end_;
148  };
149 } // namespace detail_cry
150 } // namespace kblib
151 namespace std {
152 # if defined(__clang__)
153 // Fix from: https://github.com/nlohmann/json/issues/1401
154 # pragma clang diagnostic push
155 # pragma clang diagnostic ignored "-Wmismatched-tags"
156 # endif
157 template <typename T>
158 struct tuple_size<kblib::detail_cry::value_index_pair<T>> {
159  static constexpr std::size_t value = 2;
160 };
161 
162 template <typename T>
163 struct tuple_element<0, kblib::detail_cry::value_index_pair<T>> {
164  using type = const std::size_t;
165 };
166 
167 template <typename T>
168 struct tuple_element<1, kblib::detail_cry::value_index_pair<T>> {
169  using type = std::remove_reference_t<decltype(*std::declval<T&>())>;
170 };
171 
172 # if defined(__clang__)
173 # pragma clang diagnostic pop
174 # endif
175 } // namespace std
176 
177 namespace kblib {
178 
185 template <typename Range>
186 auto cry_enumerate(Range&& range) -> auto {
188 }
189 
190 } // namespace kblib
191 
192 #endif
193 
194 #endif // ENUMERATECONTRIB_H
auto get(T &&t) -> std::conditional_t< std::is_reference_v< T >, const std::size_t &, const std::size_t >
The main namespace in which all entities from kblib are defined.
Definition: algorithm.h:44
typename std::enable_if< B, T >::type enable_if_t
Definition: fakestd.h:54
auto cry_enumerate(Range &&range) -> auto
constexpr auto range(Value min, Value max, Delta step=0) -> range_t< Value, Delta >
Constructs a range from beginning, end, and step amount. The range is half-open, that is min is in th...
Definition: iterators.h:620
constexpr auto copy(InputIt first, EndIt last, OutputIt out) -> OutputIt
Copies all elements of [first, last) to out. It also allows for a sentinel end iterator.
Definition: algorithm.h:1322
Definition: bits.h:714
decltype(std::begin(std::declval< Range & >())) iterator_type
iterator(iterator_type iter, std::size_t index=0)
auto operator==(const iterator &other) const -> bool
auto operator!=(const iterator &other) const -> bool
auto operator*() -> value_index_pair< iterator_type > &
typename value_and_index_base< Range >::iterator_type iterator_type
std::remove_reference_t< decltype(*std::declval< Iterator & >())> value_type
std::remove_reference_t< decltype(*std::declval< T & >())> type
Provides macros and basic templates used by the rest of kblib.