mingw_invoke.hpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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. #ifndef MINGW_INVOKE_H_
  13. #define MINGW_INVOKE_H_
  14. #include <type_traits> // For std::result_of, etc.
  15. #include <utility> // For std::forward
  16. #include <functional> // For std::reference_wrapper
  17. namespace mingw_stdthread
  18. {
  19. namespace detail
  20. {
  21. // For compatibility, implement std::invoke for C++11 and C++14
  22. #if __cplusplus < 201703L
  23. template<bool PMemFunc, bool PMemData>
  24. struct Invoker
  25. {
  26. template<class F, class... Args>
  27. inline static typename std::result_of<F(Args...)>::type invoke (F&& f, Args&&... args)
  28. {
  29. return std::forward<F>(f)(std::forward<Args>(args)...);
  30. }
  31. };
  32. template<bool>
  33. struct InvokerHelper;
  34. template<>
  35. struct InvokerHelper<false>
  36. {
  37. template<class T1>
  38. inline static auto get (T1&& t1) -> decltype(*std::forward<T1>(t1))
  39. {
  40. return *std::forward<T1>(t1);
  41. }
  42. template<class T1>
  43. inline static auto get (const std::reference_wrapper<T1>& t1) -> decltype(t1.get())
  44. {
  45. return t1.get();
  46. }
  47. };
  48. template<>
  49. struct InvokerHelper<true>
  50. {
  51. template<class T1>
  52. inline static auto get (T1&& t1) -> decltype(std::forward<T1>(t1))
  53. {
  54. return std::forward<T1>(t1);
  55. }
  56. };
  57. template<>
  58. struct Invoker<true, false>
  59. {
  60. template<class T, class F, class T1, class... Args>
  61. inline static auto invoke (F T::* f, T1&& t1, Args&&... args) ->\
  62. decltype((InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(std::forward<T1>(t1)).*f)(std::forward<Args>(args)...))
  63. {
  64. return (InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(std::forward<T1>(t1)).*f)(std::forward<Args>(args)...);
  65. }
  66. };
  67. template<>
  68. struct Invoker<false, true>
  69. {
  70. template<class T, class F, class T1, class... Args>
  71. inline static auto invoke (F T::* f, T1&& t1, Args&&... args) ->\
  72. decltype(InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(t1).*f)
  73. {
  74. return InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(t1).*f;
  75. }
  76. };
  77. template<class F, class... Args>
  78. struct InvokeResult
  79. {
  80. typedef Invoker<std::is_member_function_pointer<typename std::remove_reference<F>::type>::value,
  81. std::is_member_object_pointer<typename std::remove_reference<F>::type>::value &&
  82. (sizeof...(Args) == 1)> invoker;
  83. inline static auto invoke (F&& f, Args&&... args) -> decltype(invoker::invoke(std::forward<F>(f), std::forward<Args>(args)...))
  84. {
  85. return invoker::invoke(std::forward<F>(f), std::forward<Args>(args)...);
  86. }
  87. };
  88. template<class F, class...Args>
  89. auto invoke (F&& f, Args&&... args) -> decltype(InvokeResult<F, Args...>::invoke(std::forward<F>(f), std::forward<Args>(args)...))
  90. {
  91. return InvokeResult<F, Args...>::invoke(std::forward<F>(f), std::forward<Args>(args)...);
  92. }
  93. #else
  94. using std::invoke;
  95. #endif
  96. } // Namespace "detail"
  97. } // Namespace "mingw_stdthread"
  98. #endif