14#if !defined(__cpp_concepts)
15#error "This library requires concepts"
22 template<
size_t I,
typename...
Ts>
23 using nth_type_of = std::tuple_element_t<
I, std::tuple<
Ts...>>;
24 template<
typename...
Ts>
25 using first_type_of = std::tuple_element_t<0, std::tuple<
Ts...>>;
26 template<
typename...
Ts>
27 using last_type_of = std::tuple_element_t<(
sizeof...(Ts) - 1), std::tuple<
Ts...>>;
29 template <
size_t I,
typename T,
typename...
Ts>
30 auto nth_value_of(T&&
t,
Ts&&...
args)
33 return std::forward<T>(
t);
36 using return_type =
typename nth_type_of<
I, T,
Ts...>::type;
41 template <
typename...
Ts>
42 auto first_value_of(
Ts&&...
args)
44 using return_type =
typename first_type_of<
Ts...>::type;
48 template <
typename...
Ts>
49 auto last_value_of(
Ts&&...
args)
51 using return_type =
typename last_type_of<
Ts...>::type;
52 return std::forward<return_type>(nth_value_of<
sizeof...(
Ts) - 1>((std::forward<Ts>(
args))...));
59 template <
typename...
ARGS,
typename FUNC>
64 template <
typename FUNC,
typename...
ARGS>
65 requires ((
sizeof...(ARGS) % 2) == 0)
69 template<
typename...
ARGS,
typename FUNC>
73 template<
typename...
ARGS,
typename FUNC>
79 template <
typename FUNC,
typename...
ARGS>
84 template <
size_t N,
typename FUNC,
typename...
ARGS>
85 requires (
N <
sizeof...(ARGS))
95 template <
size_t Begin,
size_t End,
double&...,
typename FUNC,
typename...
ARGS>
100 template <
size_t Begin,
double&...,
typename FUNC,
typename...
ARGS>
105 template<
typename C,
typename X >
106 auto is(X
const&) ->
bool {
110 template<
typename C,
typename X >
111 requires std::is_same_v<C, X>
112 auto is(X
const&) ->
bool {
116 template<
typename C,
typename X >
117 requires (std::is_base_of_v<C, X> && !std::is_same_v<C, X>)
118 auto is(X
const&) ->
bool {
122 template<
typename C,
typename X >
123 requires (std::is_base_of_v<X, C> && !std::is_same_v<C, X>)
124 auto is(X
const& x) ->
bool {
125 return dynamic_cast<C const*
>(&x) !=
nullptr;
128 template<
typename C,
typename X >
129 requires (std::is_base_of_v<X, C> && !std::is_same_v<C, X>)
130 auto is(X
const* x) ->
bool {
131 return dynamic_cast<C const*
>(x) !=
nullptr;
134 template<
typename C,
typename X >
135 requires dereferenceable<X> && std::is_default_constructible_v<X> && std::is_same_v<C, void>
136 auto is(X
const& x) ->
bool
141 template<
typename C >
142 auto as(...) ->
auto {
146 template<
typename C,
typename X >
147 requires std::is_same_v<C, X>
148 auto as(X
const& x) ->
auto&& {
152 template<
typename C,
typename X >
153 auto as(X
const& x) ->
auto
154 requires (!std::is_same_v<C, X> && std::constructible_from<C, X const&>)
159 template<
typename C,
typename X >
160 requires std::is_base_of_v<C, X>
161 auto as(X&& x) ->
C&& {
162 return std::forward<X>(x);
165 template<
typename C,
typename X >
166 requires (std::is_base_of_v<X, C> && !std::is_same_v<C, X>)
167 auto as(X& x) ->
C& {
168 return dynamic_cast<C&
>(x);
171 template<
typename C,
typename X >
172 requires (std::is_base_of_v<X, C> && !std::is_same_v<C, X>)
173 auto as(X
const& x) ->
C const& {
174 return dynamic_cast<C const&
>(x);
177 template<
typename C,
typename X >
178 requires (std::is_base_of_v<X, C> && !std::is_same_v<C, X>)
179 auto as(X* x) ->
C* {
180 return dynamic_cast<C*
>(x);
183 template<
typename C,
typename X >
184 requires (std::is_base_of_v<X, C> && !std::is_same_v<C, X>)
185 auto as(X
const* x) ->
C const* {
186 return dynamic_cast<C const*
>(x);
192 template <
typename T,
typename>
195 template <
size_t I,
typename...
Ts>
196 struct get_index_impl : std::integral_constant<size_t, (size_t)-1>
201 template <
size_t I,
typename T,
typename...
Ts>
202 struct get_index_impl<
I, T, T,
Ts...>
203 : std::integral_constant<size_t, I>
206 template <
size_t I,
typename T,
typename U,
typename...
Ts>
207 struct get_index_impl<
I, T,
U,
Ts...>
208 : get_index_impl<I + 1, T, Ts...>
211 template <
typename T,
typename...
Ts>
212 struct get_index<T, std::
variant<Ts...>>
213 : get_index_impl<0, T, Ts...>
216 template <
typename T,
typename...
Ts>
217 struct get_index<T, std::
tuple<Ts...>>
218 : get_index_impl<0, T, Ts...>
222 template <
typename TYPE,
typename TYPE_CONTAINER>
223 inline constexpr size_t get_index_v = get_index<TYPE, TYPE_CONTAINER>::value;\
225 template <
typename TYPE,
typename TYPE_CONTAINER>
226 inline constexpr bool has_type_v = get_index<TYPE, TYPE_CONTAINER>::value != (
size_t)-1;
233 template<
typename T,
typename...
Ts>
234 auto is(std::variant<Ts...>
const& x)
236 if constexpr (std::is_same_v<T, void>)
238 if (x.valueless_by_exception())
return true;
239 if constexpr (is_any_of_v<std::monostate,
Ts...>)
240 return std::get_if<std::monostate>(&x) !=
nullptr;
242 return get_index_v<T, std::variant<
Ts...>> == x.index();
245 template<
typename T,
typename...
Ts>
246 auto as(std::variant<Ts...>
const& x)
248 return std::get<T>(x);
254 template<
typename T,
typename X>
255 requires (std::is_same_v<X, std::any> && !std::is_same_v<T, std::any> && !std::is_same_v<T, void>)
256 constexpr auto is(X
const& x) ->
bool
258 return x.type() ==
typeid(T);
261 template<
typename T,
typename X>
262 requires (std::is_same_v<X, std::any> && std::is_same_v<T, void>)
263 constexpr auto is(X
const& x) ->
bool
265 return !x.has_value();
268 template<
typename T,
typename X>
269 requires (!std::is_reference_v<T> && std::is_same_v<X, std::any> && !std::is_same_v<T, std::any>)
270 constexpr auto as(X
const& x) -> T
272 return std::any_cast<T>(x);
279 template<
typename T,
typename X>
280 requires std::is_same_v<X, std::optional<T>>
281 constexpr auto is(X
const& x) ->
bool
283 return x.has_value();
286 template<
typename T,
typename U>
287 requires std::is_same_v<T, void>
288 constexpr auto is(std::optional<U>
const& x) ->
bool
290 return !x.has_value();
293 template<
typename T,
typename X>
294 requires std::is_same_v<X, std::optional<T>>
295 constexpr auto as(X
const& x) ->
auto&&
309 template <
typename T>
310 requires (!std::is_same_v<T, pass_identity>)
311 T
operator* (T&&
obj)
const {
return std::forward<T>(
obj); }
313 pass_identity operator* (pass_identity&&)
const {
return {}; }
316 template <
typename T>
317 requires (!std::is_same_v<T, pass_identity>)
318 T
operator* (T&&
obj, pass_identity&&
p) {
return std::forward<T>(
obj); }
320 constexpr size_t not_given = std::numeric_limits<size_t>::max();
323 template <
typename FUNC,
typename...
ARGS>
324 requires ((
sizeof...(ARGS) % 2) == 0)
327 if constexpr (
sizeof...(args) > 1)
330 f(std::forward<T1>(
t1), std::forward<T2>(
t2));
331 if constexpr (
sizeof...(args) > 1)
333 }(std::forward<ARGS>(
args)...);
391 template <
size_t INDEX,
typename VALUE,
typename FUNC>
394 if constexpr (std::is_invocable_v<FUNC, std::integral_constant<size_t, INDEX>,
VALUE>)
395 func(std::integral_constant<size_t, INDEX>{}, std::forward<VALUE>(value));
396 else if constexpr (std::is_invocable_v<FUNC, VALUE, std::integral_constant<size_t, INDEX>>)
397 func(std::forward<VALUE>(value), std::integral_constant<size_t, INDEX>{});
398 else if constexpr (std::is_invocable_v<FUNC, VALUE, size_t>)
400 else if constexpr (std::is_invocable_v<FUNC, size_t, VALUE>)
402 else if constexpr (std::is_invocable_v<FUNC, VALUE>)
403 func(std::forward<VALUE>(value));
408 template <
size_t INDEX,
typename VALUE,
typename FUNC>
411 if constexpr (std::is_invocable_v<FUNC, std::integral_constant<size_t, INDEX>,
VALUE>)
412 return func(std::integral_constant<size_t, INDEX>{}, std::forward<VALUE>(value));
413 else if constexpr (std::is_invocable_v<FUNC, VALUE, std::integral_constant<size_t, INDEX>>)
414 return func(std::forward<VALUE>(value), std::integral_constant<size_t, INDEX>{});
415 else if constexpr (std::is_invocable_v<FUNC, VALUE, size_t>)
416 return func(std::forward<VALUE>(value),
INDEX);
417 else if constexpr (std::is_invocable_v<FUNC, size_t, VALUE>)
418 return func(
INDEX, std::forward<VALUE>(value));
419 else if constexpr (std::is_invocable_v<FUNC, VALUE>)
420 return func(std::forward<VALUE>(value));
425 template<
typename T,
typename FUNC,
size_t...
Is>
426 constexpr void do_for_each_in_tuple(T&&
t,
FUNC const&
f, std::index_sequence<Is...>)
433 template<
typename T,
typename FUNC,
size_t...
Is>
434 constexpr auto do_transform_tuple(T&&
t,
FUNC const&
f, std::index_sequence<Is...>)
441 template<
typename...
ARGS,
typename FUNC,
size_t...
Is>
442 constexpr void do_for_each(
FUNC const&
f, std::index_sequence<Is...>)
444 (
call<Is>(std::type_identity<ARGS>{},
f), ...);
448 template <
typename...
ARGS,
typename FUNC>
451 detail::do_for_each<
ARGS...>(std::forward<FUNC>(
f), std::make_index_sequence<
sizeof...(ARGS)>());
454 template<
typename...
ARGS,
typename FUNC>
457 detail::do_for_each_in_tuple(
t, std::forward<FUNC>(
f), std::make_index_sequence<
sizeof...(
ARGS)>());
460 template<
typename...
ARGS,
typename FUNC>
463 detail::do_for_each_in_tuple(std::move(
t), std::forward<FUNC>(
f), std::make_index_sequence<
sizeof...(
ARGS)>());
466 template<
typename...
ARGS,
typename FUNC>
469 return detail::do_transform_tuple(
t, std::forward<FUNC>(
f), std::make_index_sequence<
sizeof...(
ARGS)>());
472 template <
typename FUNC,
typename...
ARGS>
489 (detail::call<INDICES>(
490 std::get<INDICES>(
tuple)
492 }(std::forward<FUNC>(
f), std::make_index_sequence<
sizeof...(ARGS)>{}, std::forward_as_tuple(std::forward<ARGS>(
args)...));
498 template <
size_t I,
typename FUNC,
typename...
ARGS>
499 requires (
I <
sizeof...(ARGS))
502 return [&] <
size_t...
Idxs>(std::index_sequence<
Idxs...>) {
504 static_assert(std::is_invocable_v<FUNC, ARGS>,
"Cannot invoke callback with this type");
505 if constexpr (
Idxs ==
I)
506 return f(std::forward<ARGS>(
args));
508 return detail::pass_identity{};
510 }(std::make_index_sequence<
sizeof...(args)>{});
515 template <
size_t,
size_t = detail::not_given,
size_t = 1,
class = std::
integral_constant<
size_t, 0>>
518 template <
size_t Begin,
size_t End,
size_t Str
ide,
size_t I>
519 struct pack_slicer<
Begin,
End,
Stride, std::integral_constant<size_t, I>>
525 template <
typename T,
typename...
ARGS>
526 static constexpr auto make_slice_function(T&&
t,
ARGS&&...
ts)
529 if constexpr (include)
537 static constexpr auto make_slice_function() {
return [](
auto&&
cb)
mutable {
return cb(); }; }
544 return ::ghassanpl::detail::pack_slicer<Begin, End, Stride>::make_slice_function(std::forward<ARGS>(
args)...)(std::forward<FUNC>(
callback));
547 template <
size_t Begin,
size_t End,
double&...,
typename FUNC,
typename...
ARGS>
550 return ::ghassanpl::detail::pack_slicer<Begin, End>::make_slice_function(std::forward<ARGS>(
args)...)(std::forward<FUNC>(
callback));
553 template <
size_t Begin,
double&...,
typename FUNC,
typename...
ARGS>
556 return ::ghassanpl::detail::pack_slicer<Begin>::make_slice_function(std::forward<ARGS>(
args)...)(std::forward<FUNC>(
callback));
constexpr auto bit_count
Equal to the number of bits in the type.
The below code is based on Sun's libm library code, which is licensed under the following license:
Primary namespace for everything in this library.
constexpr auto transform_tuple(std::tuple< ARGS... > const &t, FUNC &&f)
Function: transform_tuple.
constexpr void for_each(FUNC &&f)
Function: for_each TODO: Description.
constexpr void for_each_pair(FUNC &&f, ARGS &&... args)
Function: for_each_pair TODO: Description.
constexpr auto apply_to_nth(FUNC &&f, ARGS &&... args)
Function: apply_to_nth Calls f on the Nth argument in the args pack.
constexpr void for_each_in_tuple(std::tuple< ARGS... > const &t, FUNC &&f)
Function: for_each_in_tuple.
constexpr auto apply_to_slice(FUNC &&f, ARGS &&... args)
Function: apply_to_slice Calls f with a slice of the args pack.
constexpr void enumerate_pack(FUNC &&f, ARGS &&... args)
Function: enumerate_pack Calls f on every argument args....
auto is(X const &) -> bool
Shamelessly stolen from hsutter's cppfront.
std::variant get index of type