OpenRCT2/src/thirdparty/dukglue/detail_traits.h

122 lines
4.9 KiB
C++

#pragma once
#include <functional>
namespace dukglue
{
namespace detail
{
//////////////////////////////////////////////////////////////////////////////////////////////
// Credit to LuaState for this code:
// https://github.com/AdUki/LuaState/blob/master/include/Traits.h
template<size_t...> struct index_tuple {};
template<size_t I, typename IndexTuple, typename ... Types>
struct make_indexes_impl;
template<size_t I, size_t... Indexes, typename T, typename ... Types>
struct make_indexes_impl<I, index_tuple<Indexes...>, T, Types...>
{
typedef typename make_indexes_impl<I + 1, index_tuple<Indexes..., I>, Types...>::type type;
};
template<size_t I, size_t... Indexes>
struct make_indexes_impl<I, index_tuple<Indexes...> >
{
typedef index_tuple<Indexes...> type;
};
template<typename ... Types>
struct make_indexes : make_indexes_impl<0, index_tuple<>, Types...>
{};
//////////////////////////////////////////////////////////////////////////////////////////////
template <std::size_t... Is>
struct indexes {};
template <std::size_t N, std::size_t... Is>
struct indexes_builder : indexes_builder<N - 1, N - 1, Is...> {};
template <std::size_t... Is>
struct indexes_builder<0, Is...> {
typedef indexes<Is...> index;
};
//////////////////////////////////////////////////////////////////////////////////////////////
// This mess is used to use function arugments stored in an std::tuple to an
// std::function, function pointer, or method.
// std::function
template<class Ret, class... Args, size_t... Indexes >
Ret apply_helper(std::function<Ret(Args...)> pf, index_tuple< Indexes... >, std::tuple<Args...>&& tup)
{
return pf(std::forward<Args>(std::get<Indexes>(tup))...);
}
template<class Ret, class ... Args>
Ret apply(std::function<Ret(Args...)> pf, const std::tuple<Args...>& tup)
{
return apply_helper(pf, typename make_indexes<Args...>::type(), std::tuple<Args...>(tup));
}
// function pointer
template<class Ret, class... Args, class... BakedArgs, size_t... Indexes >
Ret apply_fp_helper(Ret(*pf)(Args...), index_tuple< Indexes... >, std::tuple<BakedArgs...>&& tup)
{
return pf(std::forward<Args>(std::get<Indexes>(tup))...);
}
template<class Ret, class ... Args, class ... BakedArgs>
Ret apply_fp(Ret(*pf)(Args...), const std::tuple<BakedArgs...>& tup)
{
return apply_fp_helper(pf, typename make_indexes<BakedArgs...>::type(), std::tuple<BakedArgs...>(tup));
}
// method pointer
template<class Cls, class Ret, class... Args, class... BakedArgs, size_t... Indexes >
Ret apply_method_helper(Ret(Cls::*pf)(Args...), index_tuple< Indexes... >, Cls* obj, std::tuple<BakedArgs...>&& tup)
{
return (*obj.*pf)(std::forward<Args>(std::get<Indexes>(tup))...);
}
template<class Cls, class Ret, class ... Args, class... BakedArgs>
Ret apply_method(Ret(Cls::*pf)(Args...), Cls* obj, const std::tuple<BakedArgs...>& tup)
{
return apply_method_helper(pf, typename make_indexes<Args...>::type(), obj, std::tuple<BakedArgs...>(tup));
}
// const method pointer
template<class Cls, class Ret, class... Args, class... BakedArgs, size_t... Indexes >
Ret apply_method_helper(Ret(Cls::*pf)(Args...) const, index_tuple< Indexes... >, Cls* obj, std::tuple<BakedArgs...>&& tup)
{
return (*obj.*pf)(std::forward<Args>(std::get<Indexes>(tup))...);
}
template<class Cls, class Ret, class ... Args, class... BakedArgs>
Ret apply_method(Ret(Cls::*pf)(Args...) const, Cls* obj, const std::tuple<BakedArgs...>& tup)
{
return apply_method_helper(pf, typename make_indexes<Args...>::type(), obj, std::tuple<BakedArgs...>(tup));
}
// constructor
template<class Cls, typename... Args, size_t... Indexes >
Cls* apply_constructor_helper(index_tuple< Indexes... >, std::tuple<Args...>&& tup)
{
return new Cls(std::forward<Args>(std::get<Indexes>(tup))...);
}
template<class Cls, typename... Args>
Cls* apply_constructor(const std::tuple<Args...>& tup)
{
return apply_constructor_helper<Cls>(typename make_indexes<Args...>::type(), std::tuple<Args...>(tup));
}
//////////////////////////////////////////////////////////////////////////////////////////////
}
}