[modernize] Unify VariadicEvaluate using C++17 std::apply Change-Id: Iaf8ced8c2b937cb3c503e677adb96be32d6eace8
diff --git a/include/ceres/internal/variadic_evaluate.h b/include/ceres/internal/variadic_evaluate.h index 61af6b2..eaf059b 100644 --- a/include/ceres/internal/variadic_evaluate.h +++ b/include/ceres/internal/variadic_evaluate.h
@@ -33,7 +33,11 @@ #ifndef CERES_PUBLIC_INTERNAL_VARIADIC_EVALUATE_H_ #define CERES_PUBLIC_INTERNAL_VARIADIC_EVALUATE_H_ +#include <algorithm> +#include <array> #include <cstddef> +#include <functional> +#include <tuple> #include <type_traits> #include <utility> @@ -42,51 +46,6 @@ namespace ceres::internal { -// For fixed size cost functors -template <typename Functor, typename T, int... Indices> -inline bool VariadicEvaluateImpl(const Functor& functor, - T const* const* input, - T* output, - std::false_type /*is_dynamic*/, - std::integer_sequence<int, Indices...>) { - static_assert(sizeof...(Indices) > 0, - "Invalid number of parameter blocks. At least one parameter " - "block must be specified."); - return functor(input[Indices]..., output); -} - -// For dynamic sized cost functors -template <typename Functor, typename T> -inline bool VariadicEvaluateImpl(const Functor& functor, - T const* const* input, - T* output, - std::true_type /*is_dynamic*/, - std::integer_sequence<int>) { - return functor(input, output); -} - -// For ceres cost functors (not ceres::CostFunction) -template <typename ParameterDims, typename Functor, typename T> -inline bool VariadicEvaluateImpl(const Functor& functor, - T const* const* input, - T* output, - const void* /* NOT USED */) { - using ParameterBlockIndices = - std::make_integer_sequence<int, ParameterDims::kNumParameterBlocks>; - using IsDynamic = std::integral_constant<bool, ParameterDims::kIsDynamic>; - return VariadicEvaluateImpl( - functor, input, output, IsDynamic(), ParameterBlockIndices()); -} - -// For ceres::CostFunction -template <typename ParameterDims, typename Functor, typename T> -inline bool VariadicEvaluateImpl(const Functor& functor, - T const* const* input, - T* output, - const CostFunction* /* NOT USED */) { - return functor.Evaluate(input, output, nullptr); -} - // Variadic evaluate is a helper function to evaluate ceres cost function or // functors using an input, output and the parameter dimensions. There are // several ways different possibilities: @@ -103,7 +62,31 @@ inline bool VariadicEvaluate(const Functor& functor, T const* const* input, T* output) { - return VariadicEvaluateImpl<ParameterDims>(functor, input, output, &functor); + if constexpr (std::is_base_of_v<CostFunction, Functor>) { + return functor.Evaluate(input, output, nullptr); + } else { + if constexpr (ParameterDims::kIsDynamic) { + return functor(input, output); + } else { + constexpr int kNumParameterBlocks = ParameterDims::kNumParameterBlocks; + static_assert(kNumParameterBlocks > 0, + "Invalid number of parameter blocks. At least one " + "parameter block must be specified."); + + std::array<const T*, kNumParameterBlocks> parameter_blocks; + std::copy_n(input, kNumParameterBlocks, parameter_blocks.begin()); + return std::apply( + [&functor, output](auto const*... blocks) { + static_assert( + std::is_invocable_v<const Functor&, decltype(blocks)..., T*>, + "The provided Functor's operator() signature does not match " + "the expected number of parameter blocks defined in " + "ParameterDims."); + return std::invoke(functor, blocks..., output); + }, + parameter_blocks); + } + } } // When differentiating dynamically sized CostFunctions, VariadicEvaluate