Created
September 10, 2015 10:00
-
-
Save Nnwww/6321b8821f68236ed25b to your computer and use it in GitHub Desktop.
zipper.cppを動かすための諸々 (いろいろなサイトを参考に真似た物も含む
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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