Simulant  21.12-194
A portable game engine for Windows, OSX, Linux, Dreamcast, and PSP
utility.h
1 /* * Copyright (c) 2011-2017 Luke Benstead https://simulant-engine.appspot.com
2  *
3  * This file is part of Simulant.
4  *
5  * Simulant is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Simulant is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with Simulant. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef CORE_UTILITY_HPP
20 #define CORE_UTILITY_HPP
21 
22 #include <functional>
23 
24 #include <cstddef>
25 
26 #include "type_traits.h"
27 
28 namespace smlt {
29 inline namespace v1 {
30 namespace impl {
31 
32 template <class T, T... I> struct integer_sequence {
33  static_assert(
34  ::std::is_integral<T>::value,
35  "integer_sequence must use an integral type"
36  );
37 
38  template <T N> using append = integer_sequence<T, I..., N>;
39  static constexpr ::std::size_t size () noexcept { return sizeof...(I); }
40  using next = append<size()>;
41  using type = T;
42 };
43 
44 template <class T, T Index, ::std::size_t N>
46  static_assert(Index >= 0, "Index cannot be negative");
47  using type = typename sequence_generator<T, Index - 1, N - 1>::type::next;
48 };
49 
50 template <class T, T Index>
51 struct sequence_generator<T, Index, 0ul> { using type = integer_sequence<T>; };
52 
53 template < ::std::size_t Index, class T, class U, class... Types>
55  using type = typename typelist_index<Index + 1, T, Types...>::type;
56  static constexpr ::std::size_t value = Index;
57 };
58 
59 template < ::std::size_t Index, class T, class... Types>
60 struct typelist_index<Index, T, T, Types...> {
61  using type = typelist_index;
62  static constexpr ::std::size_t value = Index;
63 };
64 
65 } /* namespace impl */
66 
67 template <class T>
68 constexpr T&& forward (remove_reference_t<T>& t) noexcept {
69  return static_cast<T&&>(t);
70 }
71 
72 template <class T>
73 constexpr T&& forward (remove_reference_t<T>&& t) noexcept {
74  return static_cast<T&&>(t);
75 }
76 
77 template <class T>
78 constexpr auto move (T&& t) noexcept -> decltype(
79  static_cast<remove_reference_t<T>&&>(t)
80 ) { return static_cast<remove_reference_t<T>&&>(t); }
81 
82 
83 template <class T, T... I>
84 using integer_sequence = impl::integer_sequence<T, I...>;
85 
86 template < ::std::size_t... I>
87 using index_sequence = integer_sequence< ::std::size_t, I...>;
88 
89 template <class T, T N>
90 using make_integer_sequence = typename impl::sequence_generator<T, N, N>::type;
91 
92 template < ::std::size_t N>
93 using make_index_sequence = make_integer_sequence< ::std::size_t, N>;
94 
95 template <class T, class... Ts>
96 using typelist_index = ::std::integral_constant<
97  ::std::size_t,
98  impl::typelist_index<0ul, T, Ts...>::type::value
99 >;
100 
101 /* N3761 (with some additions) */
102 template < ::std::size_t N, class T, class... Ts>
103 struct type_at { using type = typename type_at<N - 1, Ts...>::type; };
104 
105 template <class T, class... Ts>
106 struct type_at<0ul, T, Ts...> { using type = T; };
107 
108 template < ::std::size_t N, class... Ts>
109 using type_at_t = typename type_at<N, Ts...>::type;
110 
111 template < ::std::size_t N, class T, class... Ts>
112 constexpr auto value_at (T&& value, Ts&&...) -> enable_if_t<
113  N == 0 and N < (sizeof...(Ts) + 1),
114  decltype(::smlt::forward<T>(value))
115 > { return ::smlt::forward<T>(value); }
116 
117 template < ::std::size_t N, class T, class... Ts>
118 constexpr auto value_at (T&&, Ts&&... values) -> enable_if_t<
119  N != 0 and N < (sizeof...(Ts) + 1),
120  type_at_t<N, T, Ts...>
121 > { return value_at<N - 1, Ts...>(::smlt::forward<Ts>(values)...); }
122 
123 template <class Callable>
124 struct scope_guard final {
125 
126  static_assert(
127  ::std::is_nothrow_move_constructible<Callable>::value,
128  "Given type must be nothrow move constructible"
129  );
130 
131  explicit scope_guard (Callable callable) noexcept :
132  callable { ::smlt::move(callable) },
133  dismissed { false }
134  { }
135 
136  scope_guard (scope_guard const&) = delete;
137  scope_guard (scope_guard&&) = default;
138  scope_guard () = delete;
139  ~scope_guard () noexcept { if (not this->dismissed) { callable(); } }
140 
141  scope_guard& operator = (scope_guard const&) = delete;
142  scope_guard& operator = (scope_guard&&) = default;
143 
144  void dismiss () noexcept { this->dismissed = true; }
145 
146 private:
147  Callable callable;
148  bool dismissed;
149 };
150 
151 template <class Callable>
152 auto make_scope_guard(Callable&& callable) -> scope_guard<decay_t<Callable>> {
154  ::smlt::forward<Callable>(callable)
155  };
156 }
157 
158 }} /* namespace core::v1 */
159 
160 #endif /* CORE_UTILITY_HPP */
smlt::v1::impl::typelist_index
Definition: utility.h:54
smlt
Definition: animation.cpp:25
smlt::v1::impl::integer_sequence
Definition: utility.h:32
smlt::v1::impl::sequence_generator
Definition: utility.h:45
smlt::v1::scope_guard
Definition: utility.h:124
smlt::v1::type_at
Definition: utility.h:103