emlabcpp
modern opinionated embedded C++ library
impl.h
Go to the documentation of this file.
1 
24 #pragma once
25 
26 #include "../types.h"
27 
28 #include <tuple>
29 
30 namespace emlabcpp::impl
31 {
32 
33 template < typename... Args, typename UnaryPredicate, std::size_t... Idx >
34 [[nodiscard]] constexpr std::size_t
35 find_if_impl( std::tuple< Args... > const& t, UnaryPredicate&& f, std::index_sequence< Idx... > )
36 {
37  std::size_t res = sizeof...( Args );
38  auto ff = [&]( auto const& item, std::size_t const i ) {
39  if ( f( item ) ) {
40  res = i;
41  return true;
42  }
43  return false;
44  };
45 
46  ( ff( std::get< Idx >( t ), Idx ) || ... );
47 
48  return res;
49 }
50 
51 template <
52  typename T,
53  std::size_t N,
54  range_container Container,
55  typename UnaryCallable,
56  std::size_t... Is >
57 [[nodiscard]] std::array< T, N >
58 map_f_to_a_impl( Container&& cont, UnaryCallable&& f, std::integer_sequence< std::size_t, Is... > )
59 {
60 
61  auto iter = cont.begin();
62  auto process = [&]( auto ) {
63  if constexpr ( std::is_reference_v< Container > )
64  return f( *iter++ );
65  else
66  return f( std::move( *iter++ ) );
67  };
68 
72  return std::array< T, N >{ process( Is )... };
73 }
74 
75 template <
76  typename T,
77  std::size_t N,
78  gettable_container Container,
79  typename UnaryCallable,
80  std::size_t... Is >
81 requires( !range_container< Container > )
82 [[nodiscard]] std::array< T, N > map_f_to_a_impl(
83  Container&& cont,
84  UnaryCallable const& f,
85  std::integer_sequence< std::size_t, Is... > )
86 {
87  auto process = [&cont, &f]< std::size_t i >() {
88  return f( std::get< i >( std::forward< Container >( cont ) ) );
89  };
90 
92  return std::array< T, N > { process.template operator()< Is >()... };
93 }
94 
95 template < typename >
97 
98 template < with_push_back T >
99 struct map_f_collector< T >
100 {
101  void collect( T& res, typename T::value_type val ) const
102  {
103  res.push_back( std::move( val ) );
104  }
105 };
106 
107 template < typename T >
108 requires requires( T a, typename T::value_type b ) { a.insert( b ); }
109 struct map_f_collector< T >
110 {
111  void collect( T& res, typename T::value_type val ) const
112  {
113  res.insert( std::move( val ) );
114  }
115 };
116 
117 template < typename T, std::size_t N >
118 struct map_f_collector< std::array< T, N > >
119 {
120  std::size_t i = 0;
121 
122  void collect( std::array< T, N >& res, T val )
123  {
124  res[i] = std::move( val );
125  i += 1;
126  }
127 };
128 
129 template < typename T >
130 concept map_f_collectable = requires( T item, typename T::value_type val ) {
131  map_f_collector< T >{}.collect( item, std::move( val ) );
132 };
133 
134 template < std::size_t I, typename T >
135 constexpr auto get_ith_item_from_arrays( T& arr, auto&... arrays )
136 {
137  constexpr std::size_t first_size = std::tuple_size_v< std::decay_t< T > >;
138  if constexpr ( I >= first_size )
139  return get_ith_item_from_arrays< I - first_size >( arrays... );
140  else
141  return arr[I];
142 }
143 
144 #define EMLABCPP_INDEX_MAX 32
145 #define EMLABCPP_INDEX_EXPAND( F ) \
146  F( 0 ) \
147  F( 1 ) \
148  F( 2 ) \
149  F( 3 ) \
150  F( 4 ) \
151  F( 5 ) \
152  F( 6 ) \
153  F( 7 ) \
154  F( 8 ) \
155  F( 9 ) \
156  F( 10 ) \
157  F( 11 ) \
158  F( 12 ) \
159  F( 13 ) \
160  F( 14 ) \
161  F( 15 ) \
162  F( 16 ) \
163  F( 17 ) \
164  F( 18 ) \
165  F( 19 ) \
166  F( 20 ) \
167  F( 21 ) \
168  F( 22 ) \
169  F( 23 ) \
170  F( 24 ) \
171  F( 25 ) \
172  F( 26 ) \
173  F( 27 ) \
174  F( 28 ) \
175  F( 29 ) \
176  F( 30 ) \
177  F( 31 )
178 
179 #define EMLABCPP_INDEX_SWITCH_CASE( x ) \
180  case x: \
181  if constexpr ( x < N ) \
182  return std::forward< F >( f ).template operator()< Off + x >();
183 
185 template < std::size_t Off, std::size_t N, typename F >
186 constexpr decltype( auto ) index_switch( std::size_t i, F&& f )
187 {
188  switch ( i ) {
190  default:
191  break;
192  }
193  if constexpr ( N > EMLABCPP_INDEX_MAX )
195  i - EMLABCPP_INDEX_MAX, std::forward< F >( f ) );
196 
197  abort();
198 }
199 
200 #define EMLABCPP_INDEX_SEQ( x ) \
201  if constexpr ( x < N ) \
202  f.template operator()< Off + x >();
203 
205 template < std::size_t Off, std::size_t N, typename F >
206 constexpr void index_seq( F&& f )
207 {
209  if constexpr ( N > EMLABCPP_INDEX_MAX )
210  index_seq< EMLABCPP_INDEX_MAX, N - EMLABCPP_INDEX_MAX >( std::forward< F >( f ) );
211 }
212 
213 #define EMLABCPP_INDEX_UNTIL( x ) \
214  if constexpr ( x < N ) \
215  if ( f.template operator()< Off + x >() ) \
216  return true;
217 
219 template < std::size_t Off, std::size_t N, typename F >
220 constexpr bool index_until( F&& f )
221 {
223  if constexpr ( N > EMLABCPP_INDEX_MAX )
225  std::forward< F >( f ) );
226  else
227  return false;
228 }
229 
230 } // namespace emlabcpp::impl
#define EMLABCPP_INDEX_MAX
Definition: impl.h:144
#define EMLABCPP_INDEX_EXPAND(F)
Definition: impl.h:145
#define EMLABCPP_INDEX_SEQ(x)
Definition: impl.h:200
#define EMLABCPP_INDEX_UNTIL(x)
Definition: impl.h:213
#define EMLABCPP_INDEX_SWITCH_CASE(x)
Definition: impl.h:179
MIT License.
Definition: impl.h:31
constexpr decltype(auto) index_switch(std::size_t i, F &&f)
Executes f<i> if provided i matches.
Definition: impl.h:186
constexpr auto get_ith_item_from_arrays(T &arr, auto &... arrays)
Definition: impl.h:135
constexpr std::size_t find_if_impl(std::tuple< Args... > const &t, UnaryPredicate &&f, std::index_sequence< Idx... >)
Definition: impl.h:35
constexpr void index_seq(F &&f)
Executes f<i> for i going from Off to N.
Definition: impl.h:206
std::array< T, N > map_f_to_a_impl(Container &&cont, UnaryCallable &&f, std::integer_sequence< std::size_t, Is... >)
Definition: impl.h:58
requires(!range_container< Container >) std
Definition: impl.h:81
concept map_f_collectable
Definition: impl.h:130
constexpr bool index_until(F &&f)
Executes f<i> until some is true.
Definition: impl.h:220
Definition: impl.h:96
std::variant< int64_t, float, bool, string_buffer > value_type
Definition: base.h:51
concept range_container
so, std::ranges::range is meh because it expects return of begin() being input_output_iterator,...
Definition: concepts.h:78
T res
Definition: algorithm.h:505
UnaryCallable
Definition: types.h:54
concept gettable_container
Definition: concepts.h:71
UnaryCallable && f
Definition: algorithm.h:161
N
Definition: static_storage.h:97
void collect(T &res, typename T::value_type val) const
Definition: impl.h:101
void collect(std::array< T, N > &res, T val)
Definition: impl.h:122