Path: blob/master/thirdparty/mingw-std-threads/mingw.invoke.h
9902 views
/// \file mingw.invoke.h1/// \brief Lightweight `invoke` implementation, for C++11 and C++14.2///3/// (c) 2018-2019 by Nathaniel J. McClatchey, San Jose, CA, United States4/// \author Nathaniel J. McClatchey, PhD5///6/// \copyright Simplified (2-clause) BSD License.7///8/// \note This file may become part of the mingw-w64 runtime package. If/when9/// this happens, the appropriate license will be added, i.e. this code will10/// become dual-licensed, and the current BSD 2-clause license will stay.1112#ifndef MINGW_INVOKE_H_13#define MINGW_INVOKE_H_1415#include <type_traits> // For std::result_of, etc.16#include <utility> // For std::forward17#include <functional> // For std::reference_wrapper1819namespace mingw_stdthread20{21namespace detail22{23// For compatibility, implement std::invoke for C++11 and C++1424#if __cplusplus < 201703L25template<bool PMemFunc, bool PMemData>26struct Invoker27{28template<class F, class... Args>29inline static typename std::result_of<F(Args...)>::type invoke (F&& f, Args&&... args)30{31return std::forward<F>(f)(std::forward<Args>(args)...);32}33};34template<bool>35struct InvokerHelper;3637template<>38struct InvokerHelper<false>39{40template<class T1>41inline static auto get (T1&& t1) -> decltype(*std::forward<T1>(t1))42{43return *std::forward<T1>(t1);44}4546template<class T1>47inline static auto get (const std::reference_wrapper<T1>& t1) -> decltype(t1.get())48{49return t1.get();50}51};5253template<>54struct InvokerHelper<true>55{56template<class T1>57inline static auto get (T1&& t1) -> decltype(std::forward<T1>(t1))58{59return std::forward<T1>(t1);60}61};6263template<>64struct Invoker<true, false>65{66template<class T, class F, class T1, class... Args>67inline static auto invoke (F T::* f, T1&& t1, Args&&... args) ->\68decltype((InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(std::forward<T1>(t1)).*f)(std::forward<Args>(args)...))69{70return (InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(std::forward<T1>(t1)).*f)(std::forward<Args>(args)...);71}72};7374template<>75struct Invoker<false, true>76{77template<class T, class F, class T1, class... Args>78inline static auto invoke (F T::* f, T1&& t1, Args&&... args) ->\79decltype(InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(t1).*f)80{81return InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(t1).*f;82}83};8485template<class F, class... Args>86struct InvokeResult87{88typedef Invoker<std::is_member_function_pointer<typename std::remove_reference<F>::type>::value,89std::is_member_object_pointer<typename std::remove_reference<F>::type>::value &&90(sizeof...(Args) == 1)> invoker;91inline static auto invoke (F&& f, Args&&... args) -> decltype(invoker::invoke(std::forward<F>(f), std::forward<Args>(args)...))92{93return invoker::invoke(std::forward<F>(f), std::forward<Args>(args)...);94}95};9697template<class F, class...Args>98auto invoke (F&& f, Args&&... args) -> decltype(InvokeResult<F, Args...>::invoke(std::forward<F>(f), std::forward<Args>(args)...))99{100return InvokeResult<F, Args...>::invoke(std::forward<F>(f), std::forward<Args>(args)...);101}102#else103using std::invoke;104#endif105} // Namespace "detail"106} // Namespace "mingw_stdthread"107108#endif109110111