Skip to content

Commit 898963b

Browse files
authored
Update invoke.hpp
1 parent 088ca93 commit 898963b

File tree

1 file changed

+52
-36
lines changed

1 file changed

+52
-36
lines changed

β€Žinvoke.hpp

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,80 +5,96 @@
55

66
#include "is_reference_wrapper.hpp"
77

8-
template<class Base, class T, class Derived, class... Args>
9-
auto INVOKE(T Base::*pmf, Derived&& ref, Args&&... args)
10-
-> std::enable_if_t<std::is_function_v<T> &&
11-
std::is_base_of_v<Base, std::decay_t<Derived>>,
8+
template<bool /* std::is_member_pointer */>
9+
struct InvokeSelector {
10+
template<class Base, class T, class Derived, class... Args>
11+
static auto call(T Base::*pmf, Derived&& ref, Args&&... args)
12+
-> std::enable_if_t<std::is_function_v<T> &&
13+
std::is_base_of_v<Base, std::decay_t<Derived>>,
1214
decltype((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...))>
1315
{ return (std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...); }
1416

15-
template<class Base, class T, class RefWrap, class... Args>
16-
auto INVOKE(T Base::*pmf, RefWrap&& ref, Args&&... args)
17-
-> std::enable_if_t<std::is_function_v<T> &&
18-
is_reference_wrapper_v<std::decay_t<RefWrap>>,
17+
template<class Base, class T, class RefWrap, class... Args>
18+
static auto call(T Base::*pmf, RefWrap&& ref, Args&&... args)
19+
-> std::enable_if_t<std::is_function_v<T> &&
20+
is_reference_wrapper_v<std::decay_t<RefWrap>>,
1921
decltype((ref.get().*pmf)(std::forward<Args>(args)...))>
2022
{ return (ref.get().*pmf)(std::forward<Args>(args)...); }
2123

22-
template<class Base, class T, class Pointer, class... Args>
23-
auto INVOKE(T Base::*pmf, Pointer&& ptr, Args&&... args)
24-
-> std::enable_if_t<std::is_function_v<T> &&
25-
!is_reference_wrapper_v<std::decay_t<Pointer>> &&
26-
!std::is_base_of_v<Base, std::decay_t<Pointer>>,
24+
template<class Base, class T, class Pointer, class... Args>
25+
static auto call(T Base::*pmf, Pointer&& ptr, Args&&... args)
26+
-> std::enable_if_t<std::is_function_v<T> &&
27+
!is_reference_wrapper_v<std::decay_t<Pointer>> &&
28+
!std::is_base_of_v<Base, std::decay_t<Pointer>>,
2729
decltype(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...))>
2830
{ return ((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...); }
2931

30-
template<class Base, class T, class Derived>
31-
auto INVOKE(T Base::*pmd, Derived&& ref)
32-
-> std::enable_if_t<!std::is_function_v<T> &&
33-
std::is_base_of_v<Base, std::decay_t<Derived>>,
32+
template<class Base, class T, class Derived>
33+
static auto call(T Base::*pmd, Derived&& ref)
34+
-> std::enable_if_t<!std::is_function_v<T> &&
35+
std::is_base_of_v<Base, std::decay_t<Derived>>,
3436
decltype(std::forward<Derived>(ref).*pmd)>
3537
{ return std::forward<Derived>(ref).*pmd; }
3638

37-
template<class Base, class T, class RefWrap>
38-
auto INVOKE(T Base::*pmd, RefWrap&& ref)
39-
-> std::enable_if_t<!std::is_function_v<T> &&
40-
is_reference_wrapper_v<std::decay_t<RefWrap>>,
39+
template<class Base, class T, class RefWrap>
40+
static auto call(T Base::*pmd, RefWrap&& ref)
41+
-> std::enable_if_t<!std::is_function_v<T> &&
42+
is_reference_wrapper_v<std::decay_t<RefWrap>>,
4143
decltype(ref.get().*pmd)>
4244
{ return ref.get().*pmd; }
4345

44-
template<class Base, class T, class Pointer>
45-
auto INVOKE(T Base::*pmd, Pointer&& ptr)
46-
-> std::enable_if_t<!std::is_function_v<T> &&
47-
!is_reference_wrapper_v<std::decay_t<Pointer>> &&
48-
!std::is_base_of_v<Base, std::decay_t<Pointer>>,
46+
template<class Base, class T, class Pointer>
47+
static auto call(T Base::*pmd, Pointer&& ptr)
48+
-> std::enable_if_t<!std::is_function_v<T> &&
49+
!is_reference_wrapper_v<std::decay_t<Pointer>> &&
50+
!std::is_base_of_v<Base, std::decay_t<Pointer>>,
4951
decltype((*std::forward<Pointer>(ptr)).*pmd)>
5052
{ return (*std::forward<Pointer>(ptr)).*pmd; }
53+
};
5154

52-
template<class F, class... Args>
53-
auto INVOKE(F&& f, Args&&... args)
54-
-> std::enable_if_t<!std::is_member_pointer_v<std::decay_t<F>>,
55-
decltype(std::forward<F>(f)(std::forward<Args>(args)...))>
55+
template<>
56+
struct InvokeSelector<false> {
57+
template<class F, class... Args>
58+
static auto call(F&& f, Args&&... args)
59+
-> decltype(std::forward<F>(f)(std::forward<Args>(args)...))
5660
{ return std::forward<F>(f)(std::forward<Args>(args)...); }
61+
};
5762

5863
template<class F, class... ArgTypes>
5964
auto invoke(F&& f, ArgTypes&&... args)
60-
-> decltype((INVOKE)(std::forward<F>(f), std::forward<ArgTypes>(args)...))
65+
-> decltype(
66+
InvokeSelector<std::is_member_pointer_v<std::decay_t<F>>>::call(
67+
std::forward<F>(f), std::forward<ArgTypes>(args)...)
68+
)
6169
{
62-
return (INVOKE)(std::forward<F>(f), std::forward<ArgTypes>(args)...);
70+
return InvokeSelector<std::is_member_pointer_v<std::decay_t<F>>>::call(
71+
std::forward<F>(f), std::forward<ArgTypes>(args)...);
6372
}
6473

6574
template<class R, class F, class... ArgTypes,
6675
std::enable_if_t<!std::is_void_v<R>, int> = 0,
6776
std::enable_if_t<
6877
std::is_convertible_v<
69-
decltype((INVOKE)(std::declval<F>(), std::declval<ArgTypes>()...)),
78+
decltype(
79+
InvokeSelector<std::is_member_pointer_v<std::decay_t<F>>>::call(
80+
std::declval<F>(), std::declval<ArgTypes>()...)
81+
),
7082
R
7183
>,
7284
int> = 0
7385
>
7486
R invoke(F&& f, ArgTypes&&... args) {
75-
return (INVOKE)(std::forward<F>(f), std::forward<ArgTypes>(args)...);
87+
return InvokeSelector<std::is_member_pointer_v<std::decay_t<F>>>::call(
88+
std::forward<F>(f), std::forward<ArgTypes>(args)...);
7689
}
7790

7891
template<class R, class F, class... ArgTypes,
7992
std::enable_if_t<std::is_void_v<R>, int> = 0,
80-
decltype((void)(INVOKE)(std::declval<F>(), std::declval<ArgTypes>()...),0) = 0
93+
decltype((void)InvokeSelector<std::is_member_pointer_v<std::decay_t<F>>>::call(
94+
std::declval<F>(), std::declval<ArgTypes>()...
95+
),0) = 0
8196
>
8297
void invoke(F&& f, ArgTypes&&... args) {
83-
(INVOKE)(std::forward<F>(f), std::forward<ArgTypes>(args)...);
98+
InvokeSelector<std::is_member_pointer_v<F>>::call(
99+
std::forward<F>(f), std::forward<ArgTypes>(args)...);
84100
}

0 commit comments

Comments
 (0)