Skip to content

Commit 088ca93

Browse files
authored
Update bind.hpp
1 parent f15ce30 commit 088ca93

File tree

1 file changed

+99
-41
lines changed

1 file changed

+99
-41
lines changed

β€Žbind.hpp

Lines changed: 99 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,71 +4,129 @@
44
#include <type_traits>
55
#include <tuple>
66

7+
#include "is_reference_wrapper.hpp"
78
#include "invoke.hpp"
89

9-
template<class T, class UnBoundArgTpl>
10-
constexpr T& get_final_args(std::reference_wrapper<T> tid, UnBoundArgTpl&& unbound_args) {
11-
return tid.get();
12-
}
10+
template<class TiD,
11+
bool = is_reference_wrapper_v<TiD>,
12+
bool = std::is_bind_expression_v<TiD>,
13+
bool = ((std::is_placeholder_v<TiD>) > 0)>
14+
struct BoundArgument;
1315

14-
template<class cvTiD, class UnBoundArgTpl,
15-
std::enable_if_t<std::is_bind_expression_v<std::remove_cv_t<cvTiD>>>* = nullptr>
16-
constexpr decltype(auto) get_final_args(cvTiD& tid, UnBoundArgTpl&& unbound_args) {
17-
return std::apply(tid, std::move(unbound_args));
18-
}
19-
20-
template<class cvTiD, class UnBoundArgTpl,
21-
int idx = std::is_placeholder_v<std::remove_cv_t<cvTiD>>,
22-
std::enable_if_t<(idx > 0)>* = nullptr>
23-
constexpr decltype(auto) get_final_args(cvTiD& tid, UnBoundArgTpl&& unbound_args)
24-
{
25-
return std::get<idx - 1>(unbound_args);
26-
}
16+
template<class TiD>
17+
struct BoundArgument<TiD, true, false, false> {
18+
template<class cvTiD, class... Uj>
19+
static constexpr auto value(cvTiD& tid, Uj&&...)
20+
-> typename TiD::type&
21+
{
22+
static_assert(std::is_same_v<std::remove_cv_t<cvTiD>, TiD>);
23+
return tid.get();
24+
}
25+
template<class...>
26+
using type = typename TiD::type&;
27+
template<class...>
28+
using const_type = typename TiD::type&;
29+
};
2730

28-
template<class cvTiD, class UnBoundArgTpl,
29-
std::enable_if_t<!std::is_bind_expression_v<std::remove_cv_t<cvTiD>> &&
30-
std::is_placeholder_v<std::remove_cv_t<cvTiD>> <= 0>* = nullptr>
31-
constexpr cvTiD& get_final_args(cvTiD& tid, UnBoundArgTpl&& unbound_args)
32-
{
33-
return tid;
34-
}
31+
template<class TiD>
32+
struct BoundArgument<TiD, false, true, false> {
33+
template<class cvTiD, class... Uj>
34+
static constexpr auto value(cvTiD& tid, Uj&&... uj)
35+
-> std::result_of_t<cvTiD& (Uj&&...)>
36+
{
37+
static_assert(std::is_same_v<std::remove_cv_t<cvTiD>, TiD>);
38+
return tid(std::forward<Uj>(uj)...);
39+
}
40+
template<class... Uj>
41+
using type = std::result_of_t<TiD& (Uj&&...)>;
42+
template<class... Uj>
43+
using const_type = std::result_of_t<TiD const& (Uj&&...)>;
44+
};
45+
46+
template<class TiD>
47+
struct BoundArgument<TiD, false, false, true> {
48+
static constexpr int position { std::is_placeholder_v<TiD> - 1 };
49+
template<class cvTiD, class... Uj>
50+
static constexpr auto value(cvTiD& tid, Uj&&... uj)
51+
-> std::tuple_element_t<position,std::tuple<Uj...>>
52+
{
53+
static_assert(std::is_same_v<std::remove_cv_t<cvTiD>, TiD>);
54+
return std::get<position>(std::forward_as_tuple(std::forward<Uj>(uj)...));
55+
}
56+
template<class... Uj>
57+
using type = std::tuple_element_t<position,std::tuple<Uj...>>;
58+
template<class... Uj>
59+
using const_type = std::tuple_element_t<position,std::tuple<Uj...>>;
60+
};
61+
62+
template<class TiD>
63+
const int BoundArgument<TiD, false, false, true>::position;
64+
65+
template<class TiD, bool, bool, bool>
66+
struct BoundArgument {
67+
template<class cvTiD, class... Uj>
68+
static constexpr auto value(cvTiD& tid, Uj&&...)
69+
-> cvTiD&
70+
{
71+
static_assert(std::is_same_v<std::remove_cv_t<cvTiD>, TiD>);
72+
return tid;
73+
}
74+
template<class...>
75+
using type = TiD&;
76+
template<class...>
77+
using const_type = TiD const&;
78+
};
3579

3680
template<class FD, class R, class... BoundArgs>
3781
struct Bind {
3882
FD fd;
39-
std::tuple<std::decay_t<BoundArgs>...> bound_args;
83+
std::tuple<BoundArgs...> bound_args;
4084
private:
4185
template<class cvFD, class BoundArgTpl, class... UnBoundArgs, std::size_t... idx,
42-
class T = R, std::enable_if_t<std::is_same_v<T,void(void)>>* = nullptr>
43-
static constexpr decltype(auto) unwrap_bound_args(cvFD& fd,
86+
class T = R, std::enable_if_t<std::is_same_v<T,void(void)>, int> = 0>
87+
static constexpr decltype(auto) unpack_bound_args(cvFD& fd,
4488
/* cv std::tuple<TiD...>& */ BoundArgTpl& bound_args,
4589
std::index_sequence<idx...>,
46-
/* std::tuple<Vi&&...>&& */ std::tuple<UnBoundArgs...>&& unbound_args
90+
UnBoundArgs&&... unbound_args
4791
) {
48-
return (invoke)(fd,(get_final_args)(std::get<idx>(bound_args), std::move(unbound_args))...);
92+
return (invoke)(fd, BoundArgument<BoundArgs>::value(std::get<idx>(bound_args),
93+
std::forward<UnBoundArgs>(unbound_args)...)...);
4994
}
5095
template<class cvFD, class BoundArgTpl, class... UnBoundArgs, std::size_t... idx,
51-
class T = R, std::enable_if_t<!std::is_same_v<T,void(void)>>* = nullptr>
52-
static constexpr T unwrap_bound_args(cvFD& fd,
96+
class T = R, std::enable_if_t<!std::is_same_v<T,void(void)>, int> = 0>
97+
static constexpr T unpack_bound_args(cvFD& fd,
5398
/* cv std::tuple<TiD...>& */ BoundArgTpl& bound_args,
5499
std::index_sequence<idx...>,
55-
/* std::tuple<Vi&&...>&& */ std::tuple<UnBoundArgs...>&& unbound_args
100+
UnBoundArgs&&... unbound_args
56101
) {
57-
return (invoke<T>)(fd,(get_final_args)(std::get<idx>(bound_args), std::move(unbound_args))...);
102+
return (invoke<T>)(fd,BoundArgument<BoundArgs>::value(std::get<idx>(bound_args),
103+
std::forward<UnBoundArgs>(unbound_args)...)...);
58104
}
59105
public:
60106
template<class... UnBoundArgs>
61107
constexpr decltype(auto) operator()(UnBoundArgs&&... unbound_args) {
62-
return unwrap_bound_args(fd, bound_args,
108+
static_assert(
109+
std::is_callable_v<
110+
FD& (typename BoundArgument<BoundArgs>::template type<UnBoundArgs&&...>...)
111+
>,
112+
"The target object is not callable with the given arguments."
113+
);
114+
return unpack_bound_args(fd, bound_args,
63115
std::index_sequence_for<BoundArgs...>{},
64-
std::forward_as_tuple(std::forward<UnBoundArgs>(unbound_args)...));
116+
std::forward<UnBoundArgs>(unbound_args)...);
65117
}
66118

67119
template<class... UnBoundArgs>
68120
constexpr decltype(auto) operator()(UnBoundArgs&&... unbound_args) const {
69-
return unwrap_bound_args(fd, bound_args,
121+
static_assert(
122+
std::is_callable_v<
123+
FD const& (typename BoundArgument<BoundArgs>::template const_type<UnBoundArgs&&...>...)
124+
>,
125+
"The target object is not callable with the given arguments."
126+
);
127+
return unpack_bound_args(fd, bound_args,
70128
std::index_sequence_for<BoundArgs...>{},
71-
std::forward_as_tuple(std::forward<UnBoundArgs>(unbound_args)...));
129+
std::forward<UnBoundArgs>(unbound_args)...);
72130
}
73131
};
74132

@@ -80,15 +138,15 @@ namespace std {
80138
}
81139

82140
template<class F, class... BoundArgs>
83-
constexpr Bind<std::decay_t<F>, void(void), BoundArgs...>
84-
bind(F&& f, BoundArgs&&... bound_args)
141+
constexpr Bind<std::decay_t<F>, void(void), std::decay_t<BoundArgs>...>
142+
bind(F&& f, BoundArgs&&... bound_args)
85143
{
86144
return { std::forward<F>(f), { std::forward<BoundArgs>(bound_args)... } };
87145
}
88146

89147
template<class R, class F, class... BoundArgs>
90-
constexpr Bind<std::decay_t<F>, R, BoundArgs...>
91-
bind(F&& f, BoundArgs&&... bound_args)
148+
constexpr Bind<std::decay_t<F>, R, std::decay_t<BoundArgs>...>
149+
bind(F&& f, BoundArgs&&... bound_args)
92150
{
93151
return { std::forward<F>(f), { std::forward<BoundArgs>(bound_args)... } };
94152
}

0 commit comments

Comments
 (0)