extra/otel/opentelemetry-cpp-1.8.3/api/include/opentelemetry/nostd/detail/invoke.h (123 lines of code) (raw):
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <type_traits>
#include <utility>
#include "opentelemetry/nostd/detail/decay.h"
#include "opentelemetry/nostd/detail/void.h"
#include "opentelemetry/version.h"
#define OPENTELEMETRY_RETURN(...) \
noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) { return __VA_ARGS__; }
OPENTELEMETRY_BEGIN_NAMESPACE
namespace nostd
{
namespace detail
{
template <typename T>
struct is_reference_wrapper : std::false_type
{};
template <typename T>
struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type
{};
template <bool, int>
struct Invoke;
template <>
struct Invoke<true /* pmf */, 0 /* is_base_of */>
{
template <typename R, typename T, typename Arg, typename... Args>
inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
OPENTELEMETRY_RETURN((std::forward<Arg>(arg).*pmf)(std::forward<Args>(args)...))
};
template <>
struct Invoke<true /* pmf */, 1 /* is_reference_wrapper */>
{
template <typename R, typename T, typename Arg, typename... Args>
inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
OPENTELEMETRY_RETURN((std::forward<Arg>(arg).get().*pmf)(std::forward<Args>(args)...))
};
template <>
struct Invoke<true /* pmf */, 2 /* otherwise */>
{
template <typename R, typename T, typename Arg, typename... Args>
inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
OPENTELEMETRY_RETURN(((*std::forward<Arg>(arg)).*pmf)(std::forward<Args>(args)...))
};
template <>
struct Invoke<false /* pmo */, 0 /* is_base_of */>
{
template <typename R, typename T, typename Arg>
inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
OPENTELEMETRY_RETURN(std::forward<Arg>(arg).*pmo)
};
template <>
struct Invoke<false /* pmo */, 1 /* is_reference_wrapper */>
{
template <typename R, typename T, typename Arg>
inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
OPENTELEMETRY_RETURN(std::forward<Arg>(arg).get().*pmo)
};
template <>
struct Invoke<false /* pmo */, 2 /* otherwise */>
{
template <typename R, typename T, typename Arg>
inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
OPENTELEMETRY_RETURN((*std::forward<Arg>(arg)).*pmo)
};
template <typename R, typename T, typename Arg, typename... Args>
inline constexpr auto invoke_impl(R T::*f, Arg &&arg, Args &&... args)
OPENTELEMETRY_RETURN(Invoke<std::is_function<R>::value,
(std::is_base_of<T, decay_t<Arg>>::value
? 0
: is_reference_wrapper<decay_t<Arg>>::value ? 1 : 2)>::
invoke(f, std::forward<Arg>(arg), std::forward<Args>(args)...))
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable : 4100)
#endif
template <typename F, typename... Args>
inline constexpr auto invoke_impl(F &&f, Args &&... args)
OPENTELEMETRY_RETURN(std::forward<F>(f)(std::forward<Args>(args)...))
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // namespace detail
/* clang-format off */
template <typename F, typename... Args>
inline constexpr auto invoke(F &&f, Args &&... args)
OPENTELEMETRY_RETURN(detail::invoke_impl(std::forward<F>(f), std::forward<Args>(args)...))
namespace detail
/* clang-format on */
{
template <typename Void, typename, typename...>
struct invoke_result
{};
template <typename F, typename... Args>
struct invoke_result<void_t<decltype(nostd::invoke(std::declval<F>(), std::declval<Args>()...))>,
F, Args...>
{
using type = decltype(nostd::invoke(std::declval<F>(), std::declval<Args>()...));
};
} // namespace detail
template <typename F, typename... Args>
using invoke_result = detail::invoke_result<void, F, Args...>;
template <typename F, typename... Args>
using invoke_result_t = typename invoke_result<F, Args...>::type;
namespace detail
{
template <typename Void, typename, typename...>
struct is_invocable : std::false_type
{};
template <typename F, typename... Args>
struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...> : std::true_type
{};
template <typename Void, typename, typename, typename...>
struct is_invocable_r : std::false_type
{};
template <typename R, typename F, typename... Args>
struct is_invocable_r<void_t<invoke_result_t<F, Args...>>, R, F, Args...>
: std::is_convertible<invoke_result_t<F, Args...>, R>
{};
} // namespace detail
template <typename F, typename... Args>
using is_invocable = detail::is_invocable<void, F, Args...>;
template <typename R, typename F, typename... Args>
using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
} // namespace nostd
OPENTELEMETRY_END_NAMESPACE
#undef OPENTELEMETRY_RETURN