-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d154d5a
commit 4ed8c16
Showing
5 changed files
with
475 additions
and
1 deletion.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/// \file mingw.invoke.h | ||
/// \brief Lightweight `invoke` implementation, for C++11 and C++14. | ||
/// | ||
/// (c) 2018-2019 by Nathaniel J. McClatchey, San Jose, CA, United States | ||
/// \author Nathaniel J. McClatchey, PhD | ||
/// | ||
/// \copyright Simplified (2-clause) BSD License. | ||
/// | ||
/// \note This file may become part of the mingw-w64 runtime package. If/when | ||
/// this happens, the appropriate license will be added, i.e. this code will | ||
/// become dual-licensed, and the current BSD 2-clause license will stay. | ||
|
||
#ifndef MINGW_INVOKE_H_ | ||
#define MINGW_INVOKE_H_ | ||
|
||
#include <type_traits> // For std::result_of, etc. | ||
#include <utility> // For std::forward | ||
#include <functional> // For std::reference_wrapper | ||
|
||
namespace mingw_stdthread | ||
{ | ||
namespace detail | ||
{ | ||
// For compatibility, implement std::invoke for C++11 and C++14 | ||
#if __cplusplus < 201703L | ||
template<bool PMemFunc, bool PMemData> | ||
struct Invoker | ||
{ | ||
template<class F, class... Args> | ||
inline static typename std::result_of<F(Args...)>::type invoke (F&& f, Args&&... args) | ||
{ | ||
return std::forward<F>(f)(std::forward<Args>(args)...); | ||
} | ||
}; | ||
template<bool> | ||
struct InvokerHelper; | ||
|
||
template<> | ||
struct InvokerHelper<false> | ||
{ | ||
template<class T1> | ||
inline static auto get (T1&& t1) -> decltype(*std::forward<T1>(t1)) | ||
{ | ||
return *std::forward<T1>(t1); | ||
} | ||
|
||
template<class T1> | ||
inline static auto get (const std::reference_wrapper<T1>& t1) -> decltype(t1.get()) | ||
{ | ||
return t1.get(); | ||
} | ||
}; | ||
|
||
template<> | ||
struct InvokerHelper<true> | ||
{ | ||
template<class T1> | ||
inline static auto get (T1&& t1) -> decltype(std::forward<T1>(t1)) | ||
{ | ||
return std::forward<T1>(t1); | ||
} | ||
}; | ||
|
||
template<> | ||
struct Invoker<true, false> | ||
{ | ||
template<class T, class F, class T1, class... Args> | ||
inline static auto invoke (F T::* f, T1&& t1, Args&&... args) ->\ | ||
decltype((InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(std::forward<T1>(t1)).*f)(std::forward<Args>(args)...)) | ||
{ | ||
return (InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(std::forward<T1>(t1)).*f)(std::forward<Args>(args)...); | ||
} | ||
}; | ||
|
||
template<> | ||
struct Invoker<false, true> | ||
{ | ||
template<class T, class F, class T1, class... Args> | ||
inline static auto invoke (F T::* f, T1&& t1, Args&&... args) ->\ | ||
decltype(InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(t1).*f) | ||
{ | ||
return InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(t1).*f; | ||
} | ||
}; | ||
|
||
template<class F, class... Args> | ||
struct InvokeResult | ||
{ | ||
typedef Invoker<std::is_member_function_pointer<typename std::remove_reference<F>::type>::value, | ||
std::is_member_object_pointer<typename std::remove_reference<F>::type>::value && | ||
(sizeof...(Args) == 1)> invoker; | ||
inline static auto invoke (F&& f, Args&&... args) -> decltype(invoker::invoke(std::forward<F>(f), std::forward<Args>(args)...)) | ||
{ | ||
return invoker::invoke(std::forward<F>(f), std::forward<Args>(args)...); | ||
} | ||
}; | ||
|
||
template<class F, class...Args> | ||
auto invoke (F&& f, Args&&... args) -> decltype(InvokeResult<F, Args...>::invoke(std::forward<F>(f), std::forward<Args>(args)...)) | ||
{ | ||
return InvokeResult<F, Args...>::invoke(std::forward<F>(f), std::forward<Args>(args)...); | ||
} | ||
#else | ||
using std::invoke; | ||
#endif | ||
} // Namespace "detail" | ||
} // Namespace "mingw_stdthread" | ||
|
||
#endif |
Oops, something went wrong.