-
Notifications
You must be signed in to change notification settings - Fork 457
/
Copy pathBind.hpp
140 lines (114 loc) · 3.82 KB
/
Bind.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#pragma once
#include <tuple>
#include <type_traits>
using namespace std;
template<int...>
struct IndexTuple{};
template<int N, int... Indexes>
struct MakeIndexes : MakeIndexes<N - 1, N - 1, Indexes...>{};
template<int... indexes>
struct MakeIndexes<0, indexes...>
{
typedef IndexTuple<indexes...> type;
};
template <int I>
struct Placeholder
{
};
Placeholder<1> _1; Placeholder<2> _2; Placeholder<3> _3; Placeholder<4> _4; Placeholder<5> _5;
Placeholder<6> _6; Placeholder<7> _7;Placeholder<8> _8; Placeholder<9> _9; Placeholder<10> _10;
// result type traits
template <typename F>
struct result_traits : result_traits<decltype(&F::operator())> {};
template <typename T>
struct result_traits<T*> : result_traits<T> {};
/* check function */
template <typename R, typename... P>
struct result_traits<R(*)(P...)> { typedef R type; };
/* check member function */
template <typename R, typename C, typename... P>
struct result_traits<R(C::*)(P...)> { typedef R type; };
template <typename T, class Tuple>
inline auto select(T&& val, Tuple&)->T&&
{
return std::forward<T>(val);
}
template <int I, class Tuple>
inline auto select(Placeholder<I>&, Tuple& tp) -> decltype(std::get<I - 1>(tp))
{
return std::get<I - 1>(tp);
}
// The invoker for call a callable
template <typename T>
struct is_pointer_noref
: std::is_pointer<typename std::remove_reference<T>::type>
{};
template <typename T>
struct is_memfunc_noref
: std::is_member_function_pointer<typename std::remove_reference<T>::type>
{};
template <typename R, typename F, typename... P>
inline typename std::enable_if<is_pointer_noref<F>::value,
R>::type invoke(F&& f, P&&... par)
{
return (*std::forward<F>(f))(std::forward<P>(par)...);
}
template <typename R, typename F, typename P1, typename... P>
inline typename std::enable_if<is_memfunc_noref<F>::value && is_pointer_noref<P1>::value,
R>::type invoke(F&& f, P1&& this_ptr, P&&... par)
{
return (std::forward<P1>(this_ptr)->*std::forward<F>(f))(std::forward<P>(par)...);
}
template <typename R, typename F, typename P1, typename... P>
inline typename std::enable_if<is_memfunc_noref<F>::value && !is_pointer_noref<P1>::value,
R>::type invoke(F&& f, P1&& this_obj, P&&... par)
{
return (std::forward<P1>(this_obj).*std::forward<F>(f))(std::forward<P>(par)...);
}
template <typename R, typename F, typename... P>
inline typename std::enable_if<!is_pointer_noref<F>::value && !is_memfunc_noref<F>::value,
R>::type invoke(F&& f, P&&... par)
{
return std::forward<F>(f)(std::forward<P>(par)...);
}
template<typename Fun, typename... Args>
struct Bind_t
{
typedef typename decay<Fun>::type FunType;
typedef std::tuple<typename decay<Args>::type...> ArgType;
typedef typename result_traits<FunType>::type result_type;
public:
template<class F, class... BArgs>
Bind_t(F& f, BArgs&... args) : m_func(f), m_args(args...)
{
}
template<typename F, typename... BArgs>
Bind_t(F&& f, BArgs&&... par) : m_func(std::move(f)), m_args(std::move(par)...)
{}
template <typename... CArgs>
result_type operator()(CArgs&&... args)
{
return do_call(MakeIndexes<std::tuple_size<ArgType>::value>::type(),
std::forward_as_tuple(std::forward<CArgs>(args)...));
}
template<typename ArgTuple, int... Indexes >
result_type do_call(IndexTuple< Indexes... >& in, ArgTuple& argtp)
{
return simple::invoke<result_type>(m_func, select(std::get<Indexes>(m_args),
argtp)...);
//return m_func(select(std::get<Indexes>(m_args), argtp)...);
}
private:
FunType m_func;
ArgType m_args;
};
template <typename F, typename... P>
inline Bind_t<F, P...> Bind(F&& f, P&&... par)
{
return Bind_t<F, P...>(std::forward<F>(f), std::forward<P>(par)...);
}
template <typename F, typename... P>
inline Bind_t<F, P...> Bind(F& f, P&... par)
{
return Bind_t<F, P...>(f, par...);
}