OpenKalman
invocable_on_collection.hpp
Go to the documentation of this file.
1 /* This file is part of OpenKalman, a header-only C++ library for
2  * Kalman filters and other recursive filters.
3  *
4  * Copyright (c) 2025 Christopher Lee Ogden <ogden@gatech.edu>
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
9  */
10 
16 #ifndef OPENKALMAN_INVOCABLE_ON_COLLECTION_HPP
17 #define OPENKALMAN_INVOCABLE_ON_COLLECTION_HPP
18 
19 #ifdef __cpp_lib_ranges
20 #include <ranges>
21 #else
23 #endif
24 #include "tuple_like.hpp"
25 
27 {
28  namespace detail
29  {
30 #if not defined(__cpp_lib_ranges) or __cpp_generic_lambdas < 201707L
31  template<typename R, typename F, typename = void, typename...Args>
32  struct is_invocable_on_range : std::false_type {};
33 
34  template<typename R, typename F, typename...Args>
35  struct is_invocable_on_range<R, F, std::enable_if_t<ranges::range<R>>, Args...>
36  : std::bool_constant<std::is_invocable_v<F, ranges::range_value_t<R>, Args...>> {};
37 
38 
39  template<typename Tup, typename = void>
40  struct is_invocable_on_tuple_sequence { using type = std::index_sequence<>; };
41 
42  template<typename Tup>
43  struct is_invocable_on_tuple_sequence<Tup, std::enable_if_t<tuple_like<Tup>>>
44  { using type = std::make_index_sequence<std::tuple_size_v<std::decay_t<Tup>>>; };
45 
46 
47  template<typename Tup, typename F, typename Seq, typename...Args>
48  struct is_invocable_on_tuple : std::false_type {};
49 
50  template<typename Tup, typename F, std::size_t...Ix, typename...Args>
51  struct is_invocable_on_tuple<Tup, F, std::index_sequence<Ix...>, Args...>
52  : std::bool_constant<(... and std::is_invocable_v<F&, std::tuple_element_t<Ix, Tup>, Args...>)> {};
53 #endif
54 
55  } // namespace detail
56 
57 
61  template<typename F, typename C, typename...Args>
62 #if defined(__cpp_lib_ranges) and __cpp_generic_lambdas >= 201707L
63  concept invocable_on_collection = collection<C> and
64  (not std::ranges::range<C> or std::regular_invocable<F, std::ranges::range_value_t<C>, Args&&...>) and
65  (not tuple_like<C> or
66  []<std::size_t...i>(std::index_sequence<i...>) {
67  return (... and std::regular_invocable<F&, std::tuple_element_t<i, C>, Args&&...>);
68  } (std::make_index_sequence<size_of_v<C>>{}));
69 #else
70  constexpr bool invocable_on_collection =
71  (not ranges::range<C> or detail::is_invocable_on_range<C, F, void, Args&&...>::value) and
72  (not tuple_like<C> or detail::is_invocable_on_tuple<C, F, typename detail::is_invocable_on_tuple_sequence<C>::type, Args&&...>::value);
73 #endif
74 
75 
76 } // namespace OpenKalman::collections
77 
78 #endif //OPENKALMAN_INVOCABLE_ON_COLLECTION_HPP
Definition for collections::tuple_like.
Namespace for collections.
Definition: collections.hpp:27
constexpr bool invocable_on_collection
Callable object F is invocable on each element of collection C, with additional parameters Args...
Definition: invocable_on_collection.hpp:70
Definition: tuple_reverse.hpp:103
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
Definitions implementing features of the c++ ranges library for compatibility.
constexpr bool tuple_like
T is a non-empty tuple, pair, array, or other type that acts like a tuple.
Definition: tuple_like.hpp:51