#pragma once
#include <type_traits>
namespace WTF {
template<typename T>
struct FunctionTraits;
#if USE(JSVALUE32_64)
template<typename T>
static constexpr unsigned slotsForCCallArgument()
{
static_assert(!std::is_class<T>::value || sizeof(T) <= sizeof(void*), "This doesn't support complex structs.");
static_assert(sizeof(T) == 8 || sizeof(T) <= 4, "");
if (sizeof(T) == 8)
return 2;
return 1;
}
template<typename T>
static constexpr unsigned computeCCallSlots() { return slotsForCCallArgument<T>(); }
template<typename T, typename... Ts>
static constexpr std::enable_if_t<!!sizeof...(Ts), unsigned> computeCCallSlots() { return computeCCallSlots<Ts...>() + slotsForCCallArgument<T>(); }
#endif
template<typename Result, typename... Args>
struct FunctionTraits<Result(Args...)> {
using ResultType = Result;
static constexpr bool hasResult = !std::is_same<ResultType, void>::value;
static constexpr std::size_t arity = sizeof...(Args);
template <std::size_t n, typename = std::enable_if_t<(n < arity)>>
using ArgumentType = typename std::tuple_element<n, std::tuple<Args...>>::type;
using ArgumentTypes = std::tuple<Args...>;
#if USE(JSVALUE64)
static constexpr unsigned cCallArity() { return arity; }
#else
static constexpr unsigned cCallArity() { return computeCCallSlots<Args...>(); }
#endif // USE(JSVALUE64)
};
template<typename Result, typename... Args>
struct FunctionTraits<Result(*)(Args...)> : public FunctionTraits<Result(Args...)> {
};
}
using WTF::FunctionTraits;