123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- /// \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
|