This is an automated email from the ASF dual-hosted git repository. tqchen pushed a commit to branch revert-18117-ffi-for-each-2 in repository https://gitbox.apache.org/repos/asf/tvm.git
commit 94969340f5525dc29c56895ac232fbdb4830a859 Author: Tianqi Chen <[email protected]> AuthorDate: Mon Jul 7 07:31:54 2025 -0400 Revert "[FFI] Replace `Arg2Str` with a more powerful `for_each` (#18117)" This reverts commit 49b139be8b76aef69e537c44b22a8f370cb72901. --- ffi/include/tvm/ffi/base_details.h | 21 +-------------------- ffi/include/tvm/ffi/function_details.h | 27 +++++++++++++++++++-------- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/ffi/include/tvm/ffi/base_details.h b/ffi/include/tvm/ffi/base_details.h index d078a5963a..fb7be1a955 100644 --- a/ffi/include/tvm/ffi/base_details.h +++ b/ffi/include/tvm/ffi/base_details.h @@ -29,7 +29,6 @@ #include <tvm/ffi/endian.h> #include <cstddef> -#include <type_traits> #include <utility> #if defined(_MSC_VER) @@ -136,32 +135,14 @@ namespace tvm { namespace ffi { namespace details { -// a dependent-name version of false, for static_assert -template <typename> -inline constexpr bool always_false = false; - // for each iterator struct for_each_dispatcher { template <typename F, typename... Args, size_t... I> static void run(std::index_sequence<I...>, const F& f, Args&&... args) { // NOLINT(*) - if constexpr (std::conjunction_v< - std::is_invocable<F, std::integral_constant<size_t, I>, Args>...>) { - (f(std::integral_constant<size_t, I>{}, std::forward<Args>(args)), ...); - } else if constexpr (std::conjunction_v<std::is_invocable<F, size_t, Args>...>) { - (f(I, std::forward<Args>(args)), ...); - } else if constexpr (std::conjunction_v<std::is_invocable<F, Args>...>) { - (f(std::forward<Args>(args)), ...); - } else { - static_assert(always_false<F>, "The function is not invocable with the provided arguments"); - } + (f(I, std::forward<Args>(args)), ...); } }; -// Three kinds of function F are acceptable in `for_each`: -// 1. F(size_t, Arg): argument with its index -// 2. F(Arg): just the argument -// 3. F(std::integral_constant<size_t, I>, Arg): argument with its constexpr index -// The third one can make the index available in template arguments and `if constexpr`. template <typename F, typename... Args> void for_each(const F& f, Args&&... args) { // NOLINT(*) for_each_dispatcher::run(std::index_sequence_for<Args...>{}, f, std::forward<Args>(args)...); diff --git a/ffi/include/tvm/ffi/function_details.h b/ffi/include/tvm/ffi/function_details.h index 34e9979d5d..d029c19dd1 100644 --- a/ffi/include/tvm/ffi/function_details.h +++ b/ffi/include/tvm/ffi/function_details.h @@ -36,6 +36,23 @@ namespace tvm { namespace ffi { namespace details { +template <typename ArgType> +struct Arg2Str { + template <size_t i> + TVM_FFI_INLINE static void Apply(std::ostream& os) { + using Arg = std::tuple_element_t<i, ArgType>; + if constexpr (i != 0) { + os << ", "; + } + os << i << ": " << Type2Str<Arg>::v(); + } + template <size_t... I> + TVM_FFI_INLINE static void Run(std::ostream& os, std::index_sequence<I...>) { + using TExpander = int[]; + (void)TExpander{0, (Apply<I>(os), 0)...}; + } +}; + template <typename T> static constexpr bool ArgSupported = (std::is_same_v<std::remove_const_t<std::remove_reference_t<T>>, Any> || @@ -61,16 +78,10 @@ struct FuncFunctorImpl { #endif TVM_FFI_INLINE static std::string Sig() { + using IdxSeq = std::make_index_sequence<sizeof...(Args)>; std::ostringstream ss; ss << "("; - for_each( - [&ss](auto i, const auto& v) { - if constexpr (i() != 0) { - ss << ", "; - } - ss << i() << ": " << v; - }, - Type2Str<Args>::v()...); + Arg2Str<std::tuple<Args...>>::Run(ss, IdxSeq{}); ss << ") -> " << Type2Str<R>::v(); return ss.str(); }
