// Copyright 2022 DeepMind Technologies Limited // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef MUJOCO_PYTHON_FUNC_TRAITS_H_ #define MUJOCO_PYTHON_FUNC_TRAITS_H_ #include #include namespace mujoco::util { // Forward declaration so that the public interface appears at the top of file. namespace _impl { template struct is_callable; template struct func_arg; } // namespace _impl // True if T is callable, i.e. if T is either a function pointer/reference or // is an instance of a type with operator(). template static constexpr bool is_callable_v = _impl::is_callable>::value; // Type of the Nth argument of a function or functor, where N=0 refers to the // first argument. If N exceeds the number arguments for F then // func_arg_t is void. template using func_arg_t = typename _impl::func_arg 0)>::type; template static constexpr int func_arg_count_v = _impl::func_arg::count; // ===================================================================== // IMPLEMENTATION DETAIL. FOR INTERNAL USE WITHIN THIS HEADER FILE ONLY. // ===================================================================== namespace _impl { template struct is_callable { static constexpr bool value = false; }; template struct is_callable> { static constexpr bool value = true; }; template struct is_callable { static constexpr bool value = true; }; template struct is_callable { static constexpr bool value = true; }; // Support functors by looking at its member function Func::operator(). template struct func_arg { using call = decltype( &std::remove_const_t>::operator()); using type = typename func_arg::type; static constexpr int count = func_arg::count; }; // Base case (N == 0) for function: resolve to Arg0. template struct func_arg { using type = Arg0; static constexpr int count = 1 + std::tuple_size_v>; }; // Recursive case (N > 0) for function: discard Arg0 it and resolve to N-1. template struct func_arg { using type = typename func_arg 1)>::type; static constexpr int count = 1 + std::tuple_size_v>; }; // Specialization for non-const member functions. template struct func_arg { using type = typename func_arg 0)>::type; static constexpr int count = std::tuple_size_v>; }; // Specialization for const member functions (matches lambda::operator()). template struct func_arg { using type = typename func_arg 0)>::type; static constexpr int count = std::tuple_size_v>; }; // Functions with no argument: always resolve to void. template struct func_arg { using type = void; static constexpr int count = 0; }; } // namespace _impl } // namespace mujoco::util #endif // MUJOCO_PYTHON_FUNC_TRAITS_H_