Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/mingw-std-threads/mingw.invoke.h
9902 views
1
/// \file mingw.invoke.h
2
/// \brief Lightweight `invoke` implementation, for C++11 and C++14.
3
///
4
/// (c) 2018-2019 by Nathaniel J. McClatchey, San Jose, CA, United States
5
/// \author Nathaniel J. McClatchey, PhD
6
///
7
/// \copyright Simplified (2-clause) BSD License.
8
///
9
/// \note This file may become part of the mingw-w64 runtime package. If/when
10
/// this happens, the appropriate license will be added, i.e. this code will
11
/// become dual-licensed, and the current BSD 2-clause license will stay.
12
13
#ifndef MINGW_INVOKE_H_
14
#define MINGW_INVOKE_H_
15
16
#include <type_traits> // For std::result_of, etc.
17
#include <utility> // For std::forward
18
#include <functional> // For std::reference_wrapper
19
20
namespace mingw_stdthread
21
{
22
namespace detail
23
{
24
// For compatibility, implement std::invoke for C++11 and C++14
25
#if __cplusplus < 201703L
26
template<bool PMemFunc, bool PMemData>
27
struct Invoker
28
{
29
template<class F, class... Args>
30
inline static typename std::result_of<F(Args...)>::type invoke (F&& f, Args&&... args)
31
{
32
return std::forward<F>(f)(std::forward<Args>(args)...);
33
}
34
};
35
template<bool>
36
struct InvokerHelper;
37
38
template<>
39
struct InvokerHelper<false>
40
{
41
template<class T1>
42
inline static auto get (T1&& t1) -> decltype(*std::forward<T1>(t1))
43
{
44
return *std::forward<T1>(t1);
45
}
46
47
template<class T1>
48
inline static auto get (const std::reference_wrapper<T1>& t1) -> decltype(t1.get())
49
{
50
return t1.get();
51
}
52
};
53
54
template<>
55
struct InvokerHelper<true>
56
{
57
template<class T1>
58
inline static auto get (T1&& t1) -> decltype(std::forward<T1>(t1))
59
{
60
return std::forward<T1>(t1);
61
}
62
};
63
64
template<>
65
struct Invoker<true, false>
66
{
67
template<class T, class F, class T1, class... Args>
68
inline static auto invoke (F T::* f, T1&& t1, Args&&... args) ->\
69
decltype((InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(std::forward<T1>(t1)).*f)(std::forward<Args>(args)...))
70
{
71
return (InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(std::forward<T1>(t1)).*f)(std::forward<Args>(args)...);
72
}
73
};
74
75
template<>
76
struct Invoker<false, true>
77
{
78
template<class T, class F, class T1, class... Args>
79
inline static auto invoke (F T::* f, T1&& t1, Args&&... args) ->\
80
decltype(InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(t1).*f)
81
{
82
return InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(t1).*f;
83
}
84
};
85
86
template<class F, class... Args>
87
struct InvokeResult
88
{
89
typedef Invoker<std::is_member_function_pointer<typename std::remove_reference<F>::type>::value,
90
std::is_member_object_pointer<typename std::remove_reference<F>::type>::value &&
91
(sizeof...(Args) == 1)> invoker;
92
inline static auto invoke (F&& f, Args&&... args) -> decltype(invoker::invoke(std::forward<F>(f), std::forward<Args>(args)...))
93
{
94
return invoker::invoke(std::forward<F>(f), std::forward<Args>(args)...);
95
}
96
};
97
98
template<class F, class...Args>
99
auto invoke (F&& f, Args&&... args) -> decltype(InvokeResult<F, Args...>::invoke(std::forward<F>(f), std::forward<Args>(args)...))
100
{
101
return InvokeResult<F, Args...>::invoke(std::forward<F>(f), std::forward<Args>(args)...);
102
}
103
#else
104
using std::invoke;
105
#endif
106
} // Namespace "detail"
107
} // Namespace "mingw_stdthread"
108
109
#endif
110
111