Skip to content

Commit 89bef00

Browse files
authored
Update invoke.hpp
1 parent 64350ed commit 89bef00

1 file changed

Lines changed: 96 additions & 3 deletions

File tree

invoke.hpp

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,98 @@
1+
#pragma once
2+
3+
#include <type_traits>
4+
#include <utility>
5+
6+
#include "is_reference_wrapper.hpp"
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>>,
12+
decltype((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...))>
13+
{
14+
return (std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...);
15+
}
16+
17+
template<class Base, class T, class RefWrap, class... Args>
18+
auto INVOKE(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>>,
21+
decltype((ref.get().*pmf)(std::forward<Args>(args)...))>
22+
{
23+
return (ref.get().*pmf)(std::forward<Args>(args)...);
24+
}
25+
26+
template<class Base, class T, class Pointer, class... Args>
27+
auto INVOKE(T Base::*pmf, Pointer&& ptr, Args&&... args)
28+
-> std::enable_if_t<std::is_function_v<T> &&
29+
!is_reference_wrapper_v<std::decay_t<Pointer>> &&
30+
!std::is_base_of_v<Base, std::decay_t<Pointer>>,
31+
decltype(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...))>
32+
{
33+
return ((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...);
34+
}
35+
36+
template<class Base, class T, class Derived>
37+
auto INVOKE(T Base::*pmd, Derived&& ref)
38+
-> std::enable_if_t<!std::is_function_v<T> &&
39+
std::is_base_of_v<Base, std::decay_t<Derived>>,
40+
decltype(std::forward<Derived>(ref).*pmd)>
41+
{
42+
return std::forward<Derived>(ref).*pmd;
43+
}
44+
45+
template<class Base, class T, class RefWrap>
46+
auto INVOKE(T Base::*pmd, RefWrap&& ref)
47+
-> std::enable_if_t<!std::is_function_v<T> &&
48+
is_reference_wrapper_v<std::decay_t<RefWrap>>,
49+
decltype(ref.get().*pmd)>
50+
{
51+
return ref.get().*pmd;
52+
}
53+
54+
template<class Base, class T, class Pointer>
55+
auto INVOKE(T Base::*pmd, Pointer&& ptr)
56+
-> std::enable_if_t<!std::is_function_v<T> &&
57+
!is_reference_wrapper_v<std::decay_t<Pointer>> &&
58+
!std::is_base_of_v<Base, std::decay_t<Pointer>>,
59+
decltype((*std::forward<Pointer>(ptr)).*pmd)>
60+
{
61+
return (*std::forward<Pointer>(ptr)).*pmd;
62+
}
63+
64+
template<class F, class... Args>
65+
auto INVOKE(F&& f, Args&&... args)
66+
-> std::enable_if_t<!std::is_member_pointer_v<std::decay_t<F>>,
67+
decltype(std::forward<F>(f)(std::forward<Args>(args)...))>
68+
{
69+
return std::forward<F>(f)(std::forward<Args>(args)...);
70+
}
71+
172
template<class F, class... ArgTypes>
2-
auto invoke(F&& f, ArgTypes&&... args);
73+
auto invoke(F&& f, ArgTypes&&... args)
74+
-> decltype((INVOKE)(std::forward<F>(f), std::forward<ArgTypes>(args)...))
75+
{
76+
return (INVOKE)(std::forward<F>(f), std::forward<ArgTypes>(args)...);
77+
}
78+
79+
template<class R, class F, class... ArgTypes,
80+
std::enable_if_t<!std::is_void_v<R>, int> = 0,
81+
std::enable_if_t<
82+
std::is_convertible_v<
83+
decltype((INVOKE)(std::declval<F>(), std::declval<ArgTypes>()...)),
84+
R
85+
>,
86+
int> = 0
87+
>
88+
R invoke(F&& f, ArgTypes&&... args) {
89+
return (INVOKE)(std::forward<F>(f), std::forward<ArgTypes>(args)...);
90+
}
391

4-
template<class R, class F, class... ArgTypes>
5-
R invoke(F&& f, ArgTypes&&... args);
92+
template<class R, class F, class... ArgTypes,
93+
std::enable_if_t<std::is_void_v<R>, int> = 0,
94+
decltype((void)(INVOKE)(std::declval<F>(), std::declval<ArgTypes>()...),0) = 0
95+
>
96+
void invoke(F&& f, ArgTypes&&... args) {
97+
(INVOKE)(std::forward<F>(f), std::forward<ArgTypes>(args)...);
98+
}

0 commit comments

Comments
 (0)