Molassembler  1.2.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  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  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  invoke(f, std::declval<std::tuple_element_t<Inds, Tuple>>())
106  )
107  ...>;
108  return ReturnType(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  invoke(f, pair.first),
134  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(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(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  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 = 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(!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(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 // C++17 nodiscard
320 template<class Container, class Predicate>
321 Container copy_if(const Container& container, Predicate&& predicate) {
322  Container returnContainer;
323 
324  for(const auto& value : container) {
325  if(invoke(predicate, value)) {
326  addToContainer(returnContainer, value);
327  }
328  }
329 
330  return returnContainer;
331 }
332 
333 // C++17 nodiscard
334 template<class Container>
335 Container sorted(Container container) {
336  sort(container);
337  return container;
338 }
339 
340 // C++17 nodiscard
341 template<class Container, typename Comparator>
342 Container sorted(Container container, Comparator&& comparator) {
343  sort(container, std::forward<Comparator>(comparator));
344  return container;
345 }
346 
348 template<class Container, typename T>
349 auto find(const Container& container, const T& needle) {
350  return std::find(
351  std::begin(container),
352  std::end(container),
353  needle
354  );
355 }
356 
358 template<class Container, typename UnaryPredicate>
359 auto find_if(const Container& container, UnaryPredicate&& predicate) {
360  return std::find_if(
361  std::begin(container),
362  std::end(container),
363  std::forward<UnaryPredicate>(predicate)
364  );
365 }
366 
367 template<class Container, typename T>
368 std::size_t index(const Container& container, const T& needle) {
369  const auto iter = find(container, needle);
370  if(iter == std::end(container)) {
371  throw std::out_of_range("Needle not in the haystack");
372  }
373  return iter - std::begin(container);
374 }
375 
376 template<class Container, typename UnaryPredicate>
377 std::size_t index_if(const Container& container, UnaryPredicate&& predicate) {
378  const auto iter = find_if(container, predicate);
379  if(iter == std::end(container)) {
380  throw std::out_of_range("Needle not in the haystack");
381  }
382  return iter - std::begin(container);
383 }
384 
386 template<typename T>
387 std::vector<T> iota(unsigned upperBound) {
388  std::vector<T> values(upperBound);
389 
390  std::iota(
391  std::begin(values),
392  std::end(values),
393  T(0)
394  );
395 
396  return values;
397 }
398 
400 template<class Container>
401 auto makeContainsPredicate(const Container& container) {
402  using T = Traits::getValueType<Container>;
403 
404  return [&container](const T& element) -> bool {
405  return std::find(
406  std::begin(container),
407  std::end(container),
408  element
409  ) != std::end(container);
410  };
411 }
412 
413 namespace Functor {
414 
415 template<typename Transformation>
416 struct Map {
417  Map(Transformation&& f) : t(f) {}
418 
419  template<typename Container>
420  auto operator() (const Container& c) {
421  return Temple::map(c, t);
422  }
423 
424  Transformation t;
425 };
426 
427 template<typename Transformation>
428 auto map(Transformation&& t) {
429  return Map<Transformation>(std::forward<Transformation>(t));
430 }
431 
432 } // namespace Functor
433 
434 } // namespace Temple
435 } // namespace Molassembler
436 } // namespace Scine
437 
438 #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:359
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:416
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:401
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:349
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