Files
Mujoco_WASM/python/mujoco/util/func_traits.h
T
Saran Tunyasuvunakool 3577e2cf8b Version 2.1.2: Python bindings, OBJ assets support, bugfixes.
PiperOrigin-RevId: 434731612
Change-Id: I0cfda3e7a3d1c72036764986efc252ffa1b8c6b0
2022-03-15 14:04:44 +00:00

115 lines
4.0 KiB
C++

// 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 <tuple>
#include <type_traits>
namespace mujoco::util {
// Forward declaration so that the public interface appears at the top of file.
namespace _impl {
template <typename, typename = void> struct is_callable;
template <typename, int, bool = false> 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 <typename T>
static constexpr bool is_callable_v =
_impl::is_callable<std::remove_reference_t<T>>::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<F, N> is void.
template <typename F, int N = 0>
using func_arg_t = typename _impl::func_arg<F, N, (N > 0)>::type;
template <typename F>
static constexpr int func_arg_count_v = _impl::func_arg<F, 0>::count;
// =====================================================================
// IMPLEMENTATION DETAIL. FOR INTERNAL USE WITHIN THIS HEADER FILE ONLY.
// =====================================================================
namespace _impl {
template <typename T, typename>
struct is_callable {
static constexpr bool value = false;
};
template <typename T>
struct is_callable<T, std::void_t<decltype(&T::operator())>> {
static constexpr bool value = true;
};
template <typename Return, typename... Args>
struct is_callable<Return(Args...)> {
static constexpr bool value = true;
};
template <typename Return, typename... Args>
struct is_callable<Return (*)(Args...)> {
static constexpr bool value = true;
};
// Support functors by looking at its member function Func::operator().
template <typename Func, int N, bool Recursing>
struct func_arg {
using call = decltype(
&std::remove_const_t<std::remove_reference_t<Func>>::operator());
using type = typename func_arg<call, N>::type;
static constexpr int count = func_arg<call, N>::count;
};
// Base case (N == 0) for function: resolve to Arg0.
template <typename Ret, typename Arg0, typename... Args>
struct func_arg<Ret(Arg0, Args...), 0> {
using type = Arg0;
static constexpr int count = 1 + std::tuple_size_v<std::tuple<Args...>>;
};
// Recursive case (N > 0) for function: discard Arg0 it and resolve to N-1.
template <typename Ret, int N, typename Arg0, typename... Args>
struct func_arg<Ret(Arg0, Args...), N, true> {
using type = typename func_arg<Ret(Args...), N - 1, (N > 1)>::type;
static constexpr int count = 1 + std::tuple_size_v<std::tuple<Args...>>;
};
// Specialization for non-const member functions.
template <typename C, typename Ret, int N, typename... Args>
struct func_arg<Ret (C::*)(Args...), N> {
using type = typename func_arg<Ret(Args...), N, (N > 0)>::type;
static constexpr int count = std::tuple_size_v<std::tuple<Args...>>;
};
// Specialization for const member functions (matches lambda::operator()).
template <typename C, typename Ret, int N, typename... Args>
struct func_arg<Ret (C::*)(Args...) const, N> {
using type = typename func_arg<Ret(Args...), N, (N > 0)>::type;
static constexpr int count = std::tuple_size_v<std::tuple<Args...>>;
};
// Functions with no argument: always resolve to void.
template <typename Ret, int N, bool Recursing>
struct func_arg<Ret(), N, Recursing> {
using type = void;
static constexpr int count = 0;
};
} // namespace _impl
} // namespace mujoco::util
#endif // MUJOCO_PYTHON_FUNC_TRAITS_H_