|
29 | 29 | #include <tvm/ffi/endian.h> |
30 | 30 |
|
31 | 31 | #include <cstddef> |
| 32 | +#include <type_traits> |
32 | 33 | #include <utility> |
33 | 34 |
|
34 | 35 | #if defined(_MSC_VER) |
@@ -135,14 +136,32 @@ namespace tvm { |
135 | 136 | namespace ffi { |
136 | 137 | namespace details { |
137 | 138 |
|
| 139 | +// a dependent-name version of false, for static_assert |
| 140 | +template <typename> |
| 141 | +inline constexpr bool always_false = false; |
| 142 | + |
138 | 143 | // for each iterator |
139 | 144 | struct for_each_dispatcher { |
140 | 145 | template <typename F, typename... Args, size_t... I> |
141 | 146 | static void run(std::index_sequence<I...>, const F& f, Args&&... args) { // NOLINT(*) |
142 | | - (f(I, std::forward<Args>(args)), ...); |
| 147 | + if constexpr (std::conjunction_v< |
| 148 | + std::is_invocable<F, std::integral_constant<size_t, I>, Args>...>) { |
| 149 | + (f(std::integral_constant<size_t, I>{}, std::forward<Args>(args)), ...); |
| 150 | + } else if constexpr (std::conjunction_v<std::is_invocable<F, size_t, Args>...>) { |
| 151 | + (f(I, std::forward<Args>(args)), ...); |
| 152 | + } else if constexpr (std::conjunction_v<std::is_invocable<F, Args>...>) { |
| 153 | + (f(std::forward<Args>(args)), ...); |
| 154 | + } else { |
| 155 | + static_assert(always_false<F>, "The function is not invocable with the provided arguments"); |
| 156 | + } |
143 | 157 | } |
144 | 158 | }; |
145 | 159 |
|
| 160 | +// Three kinds of function F are acceptable in `for_each`: |
| 161 | +// 1. F(size_t, Arg): argument with its index |
| 162 | +// 2. F(Arg): just the argument |
| 163 | +// 3. F(std::integral_constant<size_t, I>, Arg): argument with its constexpr index |
| 164 | +// The third one can make the index available in template arguments and `if constexpr`. |
146 | 165 | template <typename F, typename... Args> |
147 | 166 | void for_each(const F& f, Args&&... args) { // NOLINT(*) |
148 | 167 | for_each_dispatcher::run(std::index_sequence_for<Args...>{}, f, std::forward<Args>(args)...); |
|
0 commit comments