YACLib
C++ library for concurrent tasks execution
Loading...
Searching...
No Matches
type_traits.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <yaclib/fwd.hpp>
5
6#include <exception>
7#include <type_traits>
8#include <utility>
9#include <variant>
10
11namespace yaclib {
12
13// Not available in C++17, move to std if C++17 support is ever dropped
14template <typename T>
15using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
16
17template <typename... Args>
18using head_t = typename detail::Head<Args...>::Type; // NOLINT
19
20template <typename Func, typename... Arg>
21inline constexpr bool is_invocable_v = detail::IsInvocable<Func, Arg...>::Value; // NOLINT
22
23template <typename Func, typename... Arg>
24using invoke_t = typename detail::Invoke<Func, Arg...>::Type; // NOLINT
25
26template <typename T>
28
29template <typename T>
31
32template <typename T>
34
35template <typename T>
37
38template <typename T>
40
41template <typename T>
45
46template <typename T>
50
51template <typename T>
52inline constexpr bool is_task_v = detail::IsInstantiationOf<Task, T>::Value; // NOLINT
53
54// Waitable: a reference to a shared future or a non-const reference to a regular future
55template <typename T>
56inline constexpr bool is_waitable_v =
58 (!std::is_const_v<std::remove_reference_t<T>> && is_future_base_v<remove_cvref_t<T>>);
59
60// Waitable with timeout: a non-const reference to a regular future (shared futures cannot be waited with timeout)
61template <typename T>
62inline constexpr bool is_waitable_with_timeout_v =
63 (!std::is_const_v<std::remove_reference_t<T>> && is_future_base_v<remove_cvref_t<T>>);
64
65// Combinator input: futures by value
66template <typename T>
68
69template <typename T>
71
72template <typename T>
74
75template <bool Condition, typename T>
76decltype(auto) move_if(T&& arg) noexcept { // NOLINT
77 if constexpr (Condition) {
78 return std::move(std::forward<T>(arg));
79 } else {
80 return std::forward<T>(arg);
81 }
82}
83
84template <typename T, typename... List>
85inline constexpr auto kCount = (std::size_t{std::is_same_v<T, List> ? 1 : 0} + ...);
86
87template <typename T, typename... Ts>
88inline constexpr auto kContains = (std::is_same_v<T, Ts> || ...);
89
90template <typename T, typename Tuple>
91struct Prepend;
92
93template <typename T, typename... Ts>
94struct Prepend<T, std::tuple<Ts...>> {
95 using Type = std::tuple<T, Ts...>;
96};
97
98template <typename Tuple>
99struct Tail;
100
101template <typename T, typename... Ts>
102struct Tail<std::tuple<T, Ts...>> {
103 using Type = std::tuple<Ts...>;
104};
105
106template <typename Tuple>
107using tail_t = typename Tail<Tuple>::Type;
108
109template <template <typename> typename F, typename Tuple>
110struct Filter;
111
112template <template <typename> typename F>
113struct Filter<F, std::tuple<>> {
114 using Type = std::tuple<>;
115};
116
117template <template <typename> typename F, typename T>
118struct Filter<F, std::tuple<T>> {
119 using Type = std::conditional_t<F<T>::Value, std::tuple<T>, std::tuple<>>;
120};
121
122template <template <typename> typename F, typename T, typename... Ts>
123struct Filter<F, std::tuple<T, Ts...>> {
124 private:
125 using PrevType = typename Filter<F, std::tuple<Ts...>>::Type;
126
127 public:
128 using Type = std::conditional_t<F<T>::Value, typename Prepend<T, PrevType>::Type, PrevType>;
129};
130
131template <typename Tuple>
132struct Unique;
133
134template <>
135struct Unique<std::tuple<>> {
136 using Type = std::tuple<>;
137};
138
139template <typename T>
140struct Unique<std::tuple<T>> {
141 using Type = std::tuple<T>;
142};
143
144template <typename T, typename... Ts>
145struct Unique<std::tuple<T, Ts...>> {
146 private:
147 using PrevType = typename Unique<std::tuple<Ts...>>::Type;
148
149 public:
150 using Type = std::conditional_t<kContains<T, Ts...>, PrevType, typename Prepend<T, PrevType>::Type>;
151};
152
153template <typename Tuple>
154struct Variant;
155
156template <typename... Ts>
157struct Variant<std::tuple<Ts...>> {
158 using Type = std::variant<Ts...>;
159};
160
161template <typename Tuple>
163
164template <typename T>
165struct MaybeVariant<std::tuple<T>> {
166 using Type = T;
167};
168
169template <typename... Ts>
170struct MaybeVariant<std::tuple<Ts...>> {
171 using Type = std::variant<Ts...>;
172};
173
174template <typename T>
175struct WrapVoid {
176 using Type = T;
177};
178
179template <>
180struct WrapVoid<void> {
181 using Type = Unit;
182};
183
184template <typename T>
186
187template <std::size_t FromIndex, std::size_t ToIndex, typename FromTuple, typename ToTuple>
189
190template <std::size_t ToIndex, typename... From, typename... To>
191struct TranslateIndexImpl<0, ToIndex, std::tuple<From...>, std::tuple<To...>> {
192 static_assert(sizeof...(From) >= sizeof...(To));
193 static constexpr std::size_t Index() {
194 return ToIndex;
195 }
196};
197
198template <std::size_t FromIndex, std::size_t ToIndex, typename... From, typename... To>
199struct TranslateIndexImpl<FromIndex, ToIndex, std::tuple<From...>, std::tuple<To...>> {
200 static_assert(sizeof...(From) >= sizeof...(To));
201 static_assert(FromIndex != 0);
202
203 static constexpr std::size_t Index() {
204 if constexpr (std::is_same_v<head_t<From...>, head_t<To...>>) {
205 return TranslateIndexImpl<FromIndex - 1, ToIndex + 1, tail_t<std::tuple<From...>>,
206 tail_t<std::tuple<To...>>>::Index();
207 } else {
208 return TranslateIndexImpl<FromIndex - 1, ToIndex, tail_t<std::tuple<From...>>, std::tuple<To...>>::Index();
209 }
210 }
211};
212
213template <std::size_t FromIndex, typename FromTuple, typename ToTuple>
215
216template <typename T, typename Tuple>
217struct IndexOf;
218
219template <typename T, typename... Ts>
220struct IndexOf<T, std::tuple<Ts...>> {
221 static_assert(sizeof...(Ts) > 0);
222
223 static constexpr std::size_t Index() {
224 if constexpr (std::is_same_v<T, head_t<Ts...>>) {
225 return 0;
226 } else {
227 return 1 + IndexOf<T, tail_t<std::tuple<Ts...>>>::Index();
228 }
229 }
230};
231
232template <typename T, typename Tuple>
233inline constexpr std::size_t index_of_v = IndexOf<T, Tuple>::Index();
234
235template <typename T>
236constexpr bool Check() noexcept {
237 static_assert(!std::is_reference_v<T>, "T cannot be V&, just use pointer or std::reference_wrapper");
238 static_assert(!std::is_const_v<T>, "T cannot be const, because it's unnecessary");
239 static_assert(!std::is_volatile_v<T>, "T cannot be volatile, because it's unnecessary");
240 static_assert(!is_result_v<T>, "T cannot be Result, because it's ambiguous");
241 static_assert(!is_future_base_v<T>, "T cannot be Future, because it's ambiguous");
242 static_assert(!is_task_v<T>, "T cannot be Task, because it's ambiguous");
243 static_assert(!std::is_same_v<T, std::exception_ptr>, "T cannot be std::exception_ptr, because it's ambiguous");
244 static_assert(!std::is_same_v<T, Unit>, "T cannot be Unit, because Unit for internal instead of void usage");
245 return true;
246}
247
248} // namespace yaclib
typename detail::AsyncTypes< T >::Error async_error_t
constexpr bool is_waitable_v
constexpr auto kCount
typename detail::InstantiationTypes< Task, T >::Error task_error_t
typename detail::Head< Args... >::Type head_t
constexpr std::size_t index_of_v
constexpr bool is_result_v
constexpr bool is_task_v
typename detail::AsyncTypes< T >::Value async_value_t
constexpr bool is_invocable_v
decltype(auto) move_if(T &&arg) noexcept
typename WrapVoid< T >::Type wrap_void_t
constexpr bool is_combinator_input_v
typename Tail< Tuple >::Type tail_t
constexpr bool is_future_base_v
constexpr std::size_t translate_index_v
constexpr bool Check() noexcept
constexpr bool is_shared_future_base_v
Contract< V, E > MakeContract()
Creates related future and promise.
Definition contract.hpp:25
std::remove_cv_t< std::remove_reference_t< T > > remove_cvref_t
typename detail::Invoke< Func, Arg... >::Type invoke_t
constexpr bool is_waitable_with_timeout_v
typename detail::InstantiationTypes< Task, T >::Value task_value_t
typename detail::InstantiationTypes< Result, T >::Value result_value_t
typename detail::InstantiationTypes< Result, T >::Error result_error_t
constexpr auto kContains
std::conditional_t< F< T >::Value, typename Prepend< T, PrevType >::Type, PrevType > Type
std::conditional_t< F< T >::Value, std::tuple< T >, std::tuple<> > Type
static constexpr std::size_t Index()
std::conditional_t< kContains< T, Ts... >, PrevType, typename Prepend< T, PrevType >::Type > Type