sled/include/sled/apply.h
2024-03-04 18:20:17 +08:00

59 lines
1.4 KiB
C++

#pragma once
#ifndef SLED_APPLY_H
#define SLED_APPLY_H
#include <functional>
#include <tuple>
namespace sled {
namespace detail {
template<int... Seq>
struct Sequence {};
template<int N, int... Seq>
struct MakeSeq : MakeSeq<N - 1, N - 1, Seq...> {};
template<int... Seq>
struct MakeSeq<0, Seq...> {
using type = Sequence<Seq...>;
};
template<typename ReturnT, typename Func, typename Tuple, int... Seq>
ReturnT
ApplyImpl(const Func &func, const Tuple &tuple, const Sequence<Seq...> &)
{
return std::bind(func, std::get<Seq>(tuple)...)();
}
struct VoidTag {};
}// namespace detail
template<typename ReturnT,
typename Func,
typename Tuple,
typename std::enable_if<!std::is_void<ReturnT>::value, ReturnT>::type
* = nullptr>
ReturnT
apply(const Func &func, const Tuple &tuple)
{
return detail::ApplyImpl<ReturnT>(
func, tuple,
typename detail::MakeSeq<std::tuple_size<Tuple>::value>::type());
}
template<typename ReturnT = void,
typename Func,
typename Tuple,
typename std::enable_if<std::is_void<ReturnT>::value,
detail::VoidTag>::type * = nullptr>
void
apply(const Func &func, const Tuple &tuple)
{
detail::ApplyImpl<ReturnT>(
func, tuple,
typename detail::MakeSeq<std::tuple_size<Tuple>::value>::type());
}
}// namespace sled
#endif// SLED_APPLY_H