Skip to content

Instantly share code, notes, and snippets.

@Nnwww
Created September 10, 2015 10:00
Show Gist options
  • Save Nnwww/6321b8821f68236ed25b to your computer and use it in GitHub Desktop.
Save Nnwww/6321b8821f68236ed25b to your computer and use it in GitHub Desktop.
zipper.cppを動かすための諸々 (いろいろなサイトを参考に真似た物も含む
#include <utility>
#include <type_traits>
namespace m_utl
{
template <typename T>
struct identity { using type = T; };
template <std::size_t N, typename T = void>
struct indexed_identity : identity<T> {};
template <typename... Types>
struct type_tuple {};
namespace detail
{
template <typename Indices, typename... Types>
struct tpl_utl;
template <std::size_t... Indices, typename... Types>
struct tpl_utl<std::index_sequence<Indices...>, Types...>
{
private:
template <typename T>
static T eval(typename indexed_identity<Indices>::type*..., T*, ...);
public:
using type = typename decltype(
eval(static_cast<identity<Types>*>(nullptr)...)
)::type;
};
} // detail
template <std::size_t N, typename TypeTuple>
struct _type_at;
template <std::size_t N, typename... Types>
struct _type_at<N, type_tuple<Types...>>
: detail::tpl_utl<std::make_index_sequence<N>, Types...> {};
template <std::size_t N, typename TypeTuple>
using type_at = typename _type_at<N, TypeTuple>::type;
template < std::size_t I, typename Func, typename... Tp >
inline std::enable_if_t< I >= sizeof...(Tp) - 1, void >
tpl_each(std::tuple<Tp...> &tpl, const Func& fn)
{
fn(std::get<I>(tpl));
}
template < std::size_t I = 0, typename Func, typename... Tp >
inline std::enable_if_t< I < sizeof...(Tp) - 1, void >
tpl_each(std::tuple<Tp...>& tpl, const Func& fn)
{
fn(std::get<I>(tpl));
tpl_each<I + 1, Func, Tp...>(tpl, fn);
}
template < std::size_t N, std::size_t I,
typename L_Ty, typename R_Ty, typename Func >
std::enable_if_t < I >= N - 1, std::size_t >
tpl_all_of(const L_Ty& lhs, const R_Ty& rhs, Func&& fn)
{
if( !fn( std::get<I>(lhs),
std::get<I>(rhs) ) ) return I;
return N;
}
template < std::size_t N, std::size_t I = 0,
typename L_Ty, typename R_Ty, typename Func >
std::enable_if_t < I < N - 1, std::size_t >
tpl_all_of(const L_Ty& lhs, const R_Ty& rhs, Func&& fn)
{
if( !fn( std::get<I>( lhs ),
std::get<I>( rhs ) ) ) return I;
return tpl_all_of < N, I + 1 >( lhs, rhs, std::forward<Func>(fn) );
}
namespace detail
{
template<typename F, typename Tuple, size_t... I>
auto apply_impl(F&& f, Tuple&& args, std::index_sequence<I...>)
{
return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(args))...);
}
template<typename F, typename Tuple,
typename Indices = std::make_index_sequence<std::tuple_size<Tuple>::value>>
auto apply(F&& f, Tuple&& args)
{
return apply_impl(std::forward<F>(f), std::forward<Tuple>(args), Indices());
}
template<typename F, typename Tuple, size_t... I>
auto apply_impl(F&& f, const Tuple& args, std::index_sequence<I...>)
{
return std::forward<F>(f)(std::get<I>(args)...);
}
template<typename F, typename Tuple,
typename Indices = std::make_index_sequence<std::tuple_size<Tuple>::value>>
auto apply(F&& f, const Tuple& args)
{
return apply_impl(std::forward<F>(f), args, Indices());
}
template <typename F>
class apply_functor
{
F f_;
public:
explicit apply_functor(F&& f)
: f_(std::forward<F>(f)) {}
template <typename Tuple>
auto operator()(Tuple&& args)
{
return apply(std::forward<F>(f_), std::forward<Tuple>(args));
}
template <typename Tuple>
auto operator()(const Tuple& args)
{
return apply(std::forward<F>(f_), args);
}
};
} // namespace detail
template <typename F>
detail::apply_functor<F> make_apply(F&& f)
{
return detail::apply_functor<F>(std::forward<F>(f));
}
} // m_utl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment