Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
mv link map to the engine
[simgrid.git] / include / xbt / utility.hpp
1 /* Copyright (c) 2016-2018. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #ifndef XBT_UTILITY_HPP
8 #define XBT_UTILITY_HPP
9
10 #include <tuple>
11
12 namespace simgrid {
13 namespace xbt {
14
15 /** @brief Comparator class for using with std::priority_queue or boost::heap.
16  *
17  * Compare two std::pair by their first element (of type double), and return true when the first is greater than the
18  * second.  Useful to have priority queues with the smallest element on top.
19  */
20 template <class Pair> class HeapComparator {
21 public:
22   bool operator()(const Pair& a, const Pair& b) const { return a.first > b.first; }
23 };
24
25 /** @brief Erase an element given by reference from a boost::intrusive::list.
26  */
27 template <class List, class Elem> inline void intrusive_erase(List& list, Elem& elem)
28 {
29   list.erase(list.iterator_to(elem));
30 }
31
32 // integer_sequence and friends from C++14
33 // We need them to implement `apply` from C++17.
34
35 /** A compile-time sequence of integers (from C++14)
36  *
37  * `index_sequence<std::size_t,1,5,7,9>` represents the sequence `(1,5,7,9)`.
38  *
39  * @code{.cpp}
40  * template<class T, std::size_t... I>
41  * auto extract_tuple(T&& t, integer_sequence<std::size_t, I...>)
42  *   -> decltype(std::make_tuple(std::get<I>(std::forward<T>(t))...))
43  * {
44  *  return std::make_tuple(std::get<I>(std::forward<T>(t))...);
45  * }
46  *
47  * int main()
48  * {
49  *   integer_sequence<std::size_t, 1, 3> seq;
50  *   auto a = std::make_tuple(1, 2.0, false, 'a');
51  *   auto b = extract_tuple(a, seq);
52  *   std::cout << std::get<0>(b) << '\n'; // 2
53  *   std::cout << std::get<1>(b) << '\n'; // a
54  *   return 0;
55  * }
56  * @endcode
57  */
58 template<class T, T... N>
59 class integer_sequence {
60   static constexpr std::size_t size()
61   {
62     return std::tuple_size<decltype(std::make_tuple(N...))>::value;
63   }
64 };
65
66 namespace bits {
67   template<class T, long long N, long long... M>
68   struct make_integer_sequence :
69     make_integer_sequence<T, N-1, N-1, M...>
70   {};
71   template<class T, long long... M>
72   struct make_integer_sequence<T, 0, M...> {
73     typedef integer_sequence<T, (T) M...> type;
74   };
75 }
76
77 /** A compile-time sequence of integers of the form `(0,1,2,3,...,N-1)` (from C++14) */
78 template<class T, T N>
79 using make_integer_sequence = typename simgrid::xbt::bits::make_integer_sequence<T,N>::type;
80
81 /** A compile-time sequence of indices (from C++14) */
82 template<std::size_t... Ints>
83 using index_sequence = integer_sequence<std::size_t, Ints...>;
84
85 /** A compile-time sequence of indices of the form `(0,1,2,3,...,N-1)` (from C++14) */
86 template<std::size_t N>
87 using make_index_sequence = make_integer_sequence<std::size_t, N>;
88
89 /** Convert a type parameter pack into a index_sequence (from C++14) */
90 template<class... T>
91 using index_sequence_for = make_index_sequence<sizeof...(T)>;
92
93 static_assert(std::is_same< make_index_sequence<0>, index_sequence<> >::value, "seq0");
94 static_assert(std::is_same< make_index_sequence<1>, index_sequence<0> >::value, "seq1");
95 static_assert(std::is_same< make_index_sequence<2>, index_sequence<0, 1> >::value, "seq2");
96 static_assert(std::is_same< make_index_sequence<3>, index_sequence<0, 1, 2> >::value, "seq3");
97 static_assert(std::is_same< index_sequence_for<int,double,float>, make_index_sequence<3> >::value, "seq4");
98
99 }
100 }
101 #endif