invoke.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include <type_traits>
  5. #include <utility>
  6. #include "opentelemetry/nostd/detail/decay.h"
  7. #include "opentelemetry/nostd/detail/void.h"
  8. #include "opentelemetry/version.h"
  9. #define OPENTELEMETRY_RETURN(...) \
  10. noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) \
  11. { \
  12. return __VA_ARGS__; \
  13. }
  14. OPENTELEMETRY_BEGIN_NAMESPACE
  15. namespace nostd
  16. {
  17. namespace detail
  18. {
  19. template <typename T>
  20. struct is_reference_wrapper : std::false_type
  21. {};
  22. template <typename T>
  23. struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type
  24. {};
  25. template <bool, int>
  26. struct Invoke;
  27. template <>
  28. struct Invoke<true /* pmf */, 0 /* is_base_of */>
  29. {
  30. template <typename R, typename T, typename Arg, typename... Args>
  31. inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args)
  32. OPENTELEMETRY_RETURN((std::forward<Arg>(arg).*pmf)(std::forward<Args>(args)...))
  33. };
  34. template <>
  35. struct Invoke<true /* pmf */, 1 /* is_reference_wrapper */>
  36. {
  37. template <typename R, typename T, typename Arg, typename... Args>
  38. inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args)
  39. OPENTELEMETRY_RETURN((std::forward<Arg>(arg).get().*pmf)(std::forward<Args>(args)...))
  40. };
  41. template <>
  42. struct Invoke<true /* pmf */, 2 /* otherwise */>
  43. {
  44. template <typename R, typename T, typename Arg, typename... Args>
  45. inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args)
  46. OPENTELEMETRY_RETURN(((*std::forward<Arg>(arg)).*pmf)(std::forward<Args>(args)...))
  47. };
  48. template <>
  49. struct Invoke<false /* pmo */, 0 /* is_base_of */>
  50. {
  51. template <typename R, typename T, typename Arg>
  52. inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
  53. OPENTELEMETRY_RETURN(std::forward<Arg>(arg).*pmo)
  54. };
  55. template <>
  56. struct Invoke<false /* pmo */, 1 /* is_reference_wrapper */>
  57. {
  58. template <typename R, typename T, typename Arg>
  59. inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
  60. OPENTELEMETRY_RETURN(std::forward<Arg>(arg).get().*pmo)
  61. };
  62. template <>
  63. struct Invoke<false /* pmo */, 2 /* otherwise */>
  64. {
  65. template <typename R, typename T, typename Arg>
  66. inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
  67. OPENTELEMETRY_RETURN((*std::forward<Arg>(arg)).*pmo)
  68. };
  69. template <typename R, typename T, typename Arg, typename... Args>
  70. inline constexpr auto invoke_impl(R T::*f, Arg &&arg, Args &&...args) OPENTELEMETRY_RETURN(
  71. Invoke<std::is_function<R>::value,
  72. (std::is_base_of<T, decay_t<Arg>>::value ? 0
  73. : is_reference_wrapper<decay_t<Arg>>::value ? 1
  74. : 2)>::invoke(f,
  75. std::forward<Arg>(arg),
  76. std::forward<Args>(args)...))
  77. #ifdef _MSC_VER
  78. # pragma warning(push)
  79. # pragma warning(disable : 4100)
  80. #endif
  81. template <typename F, typename... Args>
  82. inline constexpr auto invoke_impl(F &&f, Args &&...args)
  83. OPENTELEMETRY_RETURN(std::forward<F>(f)(std::forward<Args>(args)...))
  84. #ifdef _MSC_VER
  85. # pragma warning(pop)
  86. #endif
  87. } // namespace detail
  88. /* clang-format off */
  89. template <typename F, typename... Args>
  90. inline constexpr auto invoke(F &&f, Args &&... args)
  91. OPENTELEMETRY_RETURN(detail::invoke_impl(std::forward<F>(f), std::forward<Args>(args)...))
  92. namespace detail
  93. /* clang-format on */
  94. {
  95. template <typename Void, typename, typename...>
  96. struct invoke_result
  97. {};
  98. template <typename F, typename... Args>
  99. struct invoke_result<void_t<decltype(nostd::invoke(std::declval<F>(), std::declval<Args>()...))>,
  100. F, Args...>
  101. {
  102. using type = decltype(nostd::invoke(std::declval<F>(), std::declval<Args>()...));
  103. };
  104. } // namespace detail
  105. template <typename F, typename... Args>
  106. using invoke_result = detail::invoke_result<void, F, Args...>;
  107. template <typename F, typename... Args>
  108. using invoke_result_t = typename invoke_result<F, Args...>::type;
  109. namespace detail
  110. {
  111. template <typename Void, typename, typename...>
  112. struct is_invocable : std::false_type
  113. {};
  114. template <typename F, typename... Args>
  115. struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...> : std::true_type
  116. {};
  117. template <typename Void, typename, typename, typename...>
  118. struct is_invocable_r : std::false_type
  119. {};
  120. template <typename R, typename F, typename... Args>
  121. struct is_invocable_r<void_t<invoke_result_t<F, Args...>>, R, F, Args...>
  122. : std::is_convertible<invoke_result_t<F, Args...>, R>
  123. {};
  124. } // namespace detail
  125. template <typename F, typename... Args>
  126. using is_invocable = detail::is_invocable<void, F, Args...>;
  127. template <typename R, typename F, typename... Args>
  128. using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
  129. } // namespace nostd
  130. OPENTELEMETRY_END_NAMESPACE
  131. #undef OPENTELEMETRY_RETURN