|
5 | 5 |
|
6 | 6 | #include "is_reference_wrapper.hpp"
|
7 | 7 |
|
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>>, |
12 | 14 | decltype((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...))>
|
13 | 15 | { return (std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...); }
|
14 | 16 |
|
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>>, |
19 | 21 | decltype((ref.get().*pmf)(std::forward<Args>(args)...))>
|
20 | 22 | { return (ref.get().*pmf)(std::forward<Args>(args)...); }
|
21 | 23 |
|
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>>, |
27 | 29 | decltype(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...))>
|
28 | 30 | { return ((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...); }
|
29 | 31 |
|
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>>, |
34 | 36 | decltype(std::forward<Derived>(ref).*pmd)>
|
35 | 37 | { return std::forward<Derived>(ref).*pmd; }
|
36 | 38 |
|
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>>, |
41 | 43 | decltype(ref.get().*pmd)>
|
42 | 44 | { return ref.get().*pmd; }
|
43 | 45 |
|
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>>, |
49 | 51 | decltype((*std::forward<Pointer>(ptr)).*pmd)>
|
50 | 52 | { return (*std::forward<Pointer>(ptr)).*pmd; }
|
| 53 | +}; |
51 | 54 |
|
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)...)) |
56 | 60 | { return std::forward<F>(f)(std::forward<Args>(args)...); }
|
| 61 | +}; |
57 | 62 |
|
58 | 63 | template<class F, class... ArgTypes>
|
59 | 64 | 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 | + ) |
61 | 69 | {
|
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)...); |
63 | 72 | }
|
64 | 73 |
|
65 | 74 | template<class R, class F, class... ArgTypes,
|
66 | 75 | std::enable_if_t<!std::is_void_v<R>, int> = 0,
|
67 | 76 | std::enable_if_t<
|
68 | 77 | 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 | + ), |
70 | 82 | R
|
71 | 83 | >,
|
72 | 84 | int> = 0
|
73 | 85 | >
|
74 | 86 | 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)...); |
76 | 89 | }
|
77 | 90 |
|
78 | 91 | template<class R, class F, class... ArgTypes,
|
79 | 92 | 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 |
81 | 96 | >
|
82 | 97 | 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)...); |
84 | 100 | }
|
0 commit comments