Molassembler  3.0.0
Molecule graph and conformer library
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Functional.h
Go to the documentation of this file.
1 
13 #ifndef INCLUDE_MOLASSEMBLER_TEMPLE_FUNCTIONAL_H
14 #define INCLUDE_MOLASSEMBLER_TEMPLE_FUNCTIONAL_H
15 
18 
19 #include <numeric>
20 
21 namespace Scine {
22 namespace Molassembler {
23 namespace Temple {
24 
25 template<
26  class Container,
27  std::enable_if_t<Traits::hasSize<Container>::value, int> = 0
28 > auto size(const Container& container) {
29  return container.size();
30 }
31 
32 template<
33  class Container,
34  std::enable_if_t<!Traits::hasSize<Container>::value, int> = 0
35 > auto size(const Container& container) {
36  return std::distance(
37  std::begin(container),
38  std::end(container)
39  );
40 }
41 
68 template<
69  class UnaryFunction,
70  typename T,
71  template<typename, typename...> class Container,
72  template<typename> class ... Dependents
73 > auto map_stl(
74  const Container<T, Dependents<T>...>& container,
75  UnaryFunction&& function
76 ) {
77  using U = decltype(
78  Temple::invoke(function, *std::begin(container))
79  );
80 
81  Container<U, Dependents<U>...> returnContainer;
82  reserveIfPossible(returnContainer, container);
83 
84  for(const auto& element : container) {
86  returnContainer,
87  Temple::invoke(function, element)
88  );
89  }
90 
91  return returnContainer;
92 }
93 
94 namespace Detail {
95 
96 template<
97  template<typename ...> class Tuplelike,
98  typename Tuple,
99  typename Unary,
100  std::size_t ... Inds
101 >
102 constexpr auto mapTupleHelper(Tuple&& tup, Unary&& f, std::index_sequence<Inds ...> /* inds */) {
103  using ReturnType = Tuplelike<
104  decltype(
105  Temple::invoke(f, std::declval<std::tuple_element_t<Inds, Tuple>>())
106  )
107  ...>;
108  return ReturnType(Temple::invoke(f, std::get<Inds>(tup))...);
109 }
110 
111 } // namespace Detail
112 
113 template<
114  template<typename ...> class Tuplelike,
115  typename Unary,
116  typename ... Ts,
117  std::enable_if_t<!Traits::isPairlike<Tuplelike<Ts...>>::value && Traits::isTuplelike<Tuplelike<Ts...>>::value>* = nullptr
118 > constexpr auto map(Tuplelike<Ts...>&& tup, Unary&& f) {
119  return Detail::mapTupleHelper<Tuplelike>(
120  std::forward<Tuplelike<Ts...>>(tup),
121  std::forward<Unary>(f),
122  std::make_index_sequence<std::tuple_size<Tuplelike<Ts...>>::value> {}
123  );
124 }
125 
126 // Catch pair-like classes that can't provide an overload for tuple_size
127 template<
128  typename Pairlike,
129  typename Unary,
130  std::enable_if_t<Traits::isPairlike<Pairlike>::value && !Traits::isTuplelike<Pairlike>::value>* = nullptr
131 > constexpr auto map(Pairlike&& pair, Unary&& f) {
132  return std::make_pair(
133  Temple::invoke(f, pair.first),
134  Temple::invoke(f, pair.second)
135  );
136 }
137 
142 template<class Container, class UnaryFunction, std::enable_if_t<!Traits::isPairlike<Container>::value && !Traits::isTuplelike<Container>::value>* = nullptr>
143 auto map(Container&& container, UnaryFunction&& function) {
144  using U = decltype(Temple::invoke(function, *std::begin(container)));
145 
146  std::vector<U> returnContainer;
147  reserveIfPossible(returnContainer, container);
148 
149  for(auto&& value : container) {
150  returnContainer.push_back(Temple::invoke(function, std::move(value)));
151  }
152 
153  return returnContainer;
154 }
155 
157 template<class Container, class Callable>
158 void forEach(const Container& container, Callable&& callable) {
159  for(const auto& value : container) {
160  Temple::invoke(callable, value);
161  }
162 }
163 
177 template<
178  class Container,
179  typename ComparisonFunction,
180  typename MappingFunction
181 >
182 typename Container::const_iterator select(
183  const Container& container,
184  ComparisonFunction&& comparator,
185  MappingFunction&& mapFunction
186 ) {
187  auto selection = std::begin(container);
188  auto selectionValue = mapFunction(*selection);
189 
190  auto iter = std::begin(container);
191 
192  while(iter != std::end(container)) {
193  auto currentValue = mapFunction(*iter);
194 
195  // Replace if 'better' according to the comparator
196  if(comparator(currentValue, selectionValue)) {
197  selection = iter;
198  selectionValue = currentValue;
199  }
200 
201  ++iter;
202  }
203 
204  return selection;
205 }
206 
212 template<
213  class Container,
214  typename T,
215  class BinaryFunction
217  const Container& container,
218  T init,
219  BinaryFunction&& reductionFunction
220 ) {
221  for(const auto& value: container) {
222  // Call variadic invoke (no tuple unpacking!)
223  init = Temple::invoke(reductionFunction, std::move(init), value);
224  }
225 
226  return init;
227 }
228 
233 template<class Container, class UnaryPredicate = Functor::Identity>
234 bool all_of(const Container& container, UnaryPredicate&& predicate = UnaryPredicate {}) {
235  for(const auto& element : container) {
236  if(!Temple::invoke(predicate, element)) {
237  return false;
238  }
239  }
240 
241  return true;
242 }
243 
248 template<class Container, class UnaryPredicate = Functor::Identity>
249 bool any_of(const Container& container, UnaryPredicate&& predicate = UnaryPredicate {}) {
250  for(const auto& element : container) {
251  if(Temple::invoke(predicate, element)) {
252  return true;
253  }
254  }
255 
256  return false;
257 }
258 
260 template<class Container>
261 void sort(Container& container) {
262  std::sort(
263  std::begin(container),
264  std::end(container)
265  );
266 }
267 
269 template<class Container, typename Comparator>
270 void sort(Container& container, Comparator&& comparator) {
271  std::sort(
272  std::begin(container),
273  std::end(container),
274  std::forward<Comparator>(comparator)
275  );
276 }
277 
279 template<class Container>
280 void reverse(Container& container) {
281  std::reverse(
282  std::begin(container),
283  std::end(container)
284  );
285 }
286 
288 template<class Container, typename T>
289 void remove(
290  Container& container,
291  const T& value
292 ) {
293  container.erase(
294  std::remove(
295  std::begin(container),
296  std::end(container),
297  value
298  ),
299  std::end(container)
300  );
301 }
302 
304 template<class Container, class UnaryFunction>
306  Container& container,
307  UnaryFunction&& predicate
308 ) {
309  container.erase(
311  std::begin(container),
312  std::end(container),
313  std::forward<UnaryFunction>(predicate)
314  ),
315  std::end(container)
316  );
317 }
318 
319 template<class Container, class Predicate>
320 [[nodiscard]] Container copy_if(const Container& container, Predicate&& predicate) {
321  Container returnContainer;
322 
323  for(const auto& value : container) {
324  if(Temple::invoke(predicate, value)) {
325  addToContainer(returnContainer, value);
326  }
327  }
328 
329  return returnContainer;
330 }
331 
332 template<class Container>
333 [[nodiscard]] Container sorted(Container container) {
334  sort(container);
335  return container;
336 }
337 
338 template<class Container, typename Comparator>
339 [[nodiscard]] Container sorted(Container container, Comparator&& comparator) {
340  sort(container, std::forward<Comparator>(comparator));
341  return container;
342 }
343 
345 template<class Container, typename T>
346 auto find(const Container& container, const T& needle) {
347  return std::find(
348  std::begin(container),
349  std::end(container),
350  needle
351  );
352 }
353 
355 template<class Container, typename UnaryPredicate>
356 auto find_if(const Container& container, UnaryPredicate&& predicate) {
357  return std::find_if(
358  std::begin(container),
359  std::end(container),
360  std::forward<UnaryPredicate>(predicate)
361  );
362 }
363 
364 template<class Container, typename T>
365 std::size_t index(const Container& container, const T& needle) {
366  const auto iter = find(container, needle);
367  if(iter == std::end(container)) {
368  throw std::out_of_range("Needle not in the haystack");
369  }
370  return iter - std::begin(container);
371 }
372 
373 template<class Container, typename UnaryPredicate>
374 std::size_t index_if(const Container& container, UnaryPredicate&& predicate) {
375  const auto iter = find_if(container, predicate);
376  if(iter == std::end(container)) {
377  throw std::out_of_range("Needle not in the haystack");
378  }
379  return iter - std::begin(container);
380 }
381 
383 template<typename T>
384 std::vector<T> iota(unsigned upperBound) {
385  std::vector<T> values(upperBound);
386 
387  std::iota(
388  std::begin(values),
389  std::end(values),
390  T(0)
391  );
392 
393  return values;
394 }
395 
397 template<class Container>
398 auto makeContainsPredicate(const Container& container) {
399  using T = Traits::getValueType<Container>;
400 
401  return [&container](const T& element) -> bool {
402  return std::find(
403  std::begin(container),
404  std::end(container),
405  element
406  ) != std::end(container);
407  };
408 }
409 
410 namespace Functor {
411 
412 template<typename Transformation>
413 struct Map {
414  Map(Transformation&& f) : t(f) {}
415 
416  template<typename Container>
417  auto operator() (const Container& c) {
418  return Temple::map(c, t);
419  }
420 
421  Transformation t;
422 };
423 
424 template<typename Transformation>
425 auto map(Transformation&& t) {
426  return Map<Transformation>(std::forward<Transformation>(t));
427 }
428 
429 } // namespace Functor
430 
431 } // namespace Temple
432 } // namespace Molassembler
433 } // namespace Scine
434 
435 #endif
void sort(Container &container)
Calls std::sort on a container.
Definition: Functional.h:261
PURITY_STRONG constexpr std::enable_if_t< std::is_arithmetic< T >::value, ArrayType< T, size >> iota()
Iota for any array type.
Definition: Containers.h:146
Uniform callable invoke from arguments or tuple of arguments.
void remove_if(Container &container, UnaryFunction &&predicate)
Applies erase-remove idiom in-place to container with a predicate function.
Definition: Functional.h:305
auto find_if(const Container &container, UnaryPredicate &&predicate)
std::find_if shorthand
Definition: Functional.h:356
double element(const PositionCollection &normalizedPositions, const Elements::Rotation &rotation)
Returns the CSM for a Rotation symmetry element along the rotation axis without optimizing the coordi...
unsigned size(Shape shape)
Fetch the number of vertices of a shape.
auto map_stl(const Container< T, Dependents< T >...> &container, UnaryFunction &&function)
Definition: Functional.h:73
void reserveIfPossible(TargetContainer &target, const SourceContainer &source, SizeModifierUnary &&sourceModifierUnary=SizeModifierUnary{})
Rerves the space required in the target container if size can be determined from the source container...
Definition: AddToContainer.h:201
Definition: Functional.h:413
Central interface to add elements to many types of containers.
void remove(Container &container, const T &value)
Applies erase-remove idiom in-place to container.
Definition: Functional.h:289
T accumulate(const Container &container, T init, BinaryFunction &&reductionFunction)
Accumulate shorthand.
Definition: Functional.h:216
void forEach(const Container &container, Callable &&callable)
Apply a callable for all values of a container.
Definition: Functional.h:158
void reverse(Container &container)
In-place reversal.
Definition: Functional.h:280
bool any_of(const Container &container, UnaryPredicate &&predicate=UnaryPredicate{})
any_of shorthand
Definition: Functional.h:249
constexpr auto map(const ArrayType< T, size > &array, UnaryFunction &&function)
Maps all elements of any array-like container with a unary function.
Definition: Containers.h:63
auto makeContainsPredicate(const Container &container)
Creates a predicate that uses std::find for the container&#39;s value type.
Definition: Functional.h:398
Container::const_iterator select(const Container &container, ComparisonFunction &&comparator, MappingFunction &&mapFunction)
Select a value from a container.
Definition: Functional.h:182
void addToContainer(Container &container, const T &value)
Adds an lvalue element to a container by calling the container&#39;s insert or push_back member functions...
Definition: AddToContainer.h:179
auto find(const Container &container, const T &needle)
std::find shorthand
Definition: Functional.h:346
auto invoke(Function &&function, const boost::tuples::cons< HT, TT > &tuple)
Invokes a function with all values in a given boost tuple.
Definition: Invoke.h:44
bool all_of(const Container &container, UnaryPredicate &&predicate=UnaryPredicate{})
all_of shorthand
Definition: Functional.h:234