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
3680template <class FD , class R , class ... BoundArgs>
3781struct Bind {
3882 FD fd;
39- std::tuple<std:: decay_t < BoundArgs> ...> bound_args;
83+ std::tuple<BoundArgs...> bound_args;
4084private:
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 }
59105public:
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
82140template <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
89147template <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