|
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