// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include // IWYU pragma: keep #include #include #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd { template class function_ref; // IWYU pragma: keep /** * Non-owning function reference that can be used as a more performant * replacement for std::function when ownership sematics aren't needed. * * See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0792r0.html * * Based off of https://stackoverflow.com/a/39087660/4447365 */ template class function_ref { void *callable_ = nullptr; R (*invoker_)(void *, Args...) = nullptr; template using FunctionPointer = decltype(std::addressof(std::declval())); template void BindTo(F &f) noexcept { callable_ = static_cast(std::addressof(f)); invoker_ = [](void *callable, Args... args) -> R { return (*static_cast>(callable))(std::forward(args)...); }; } template void BindTo(R_in (*f)(Args_in...)) noexcept { using F = decltype(f); if (f == nullptr) { return BindTo(nullptr); } callable_ = reinterpret_cast(f); invoker_ = [](void *callable, Args... args) -> R { return (F(callable))(std::forward(args)...); }; } void BindTo(std::nullptr_t) noexcept { callable_ = nullptr; invoker_ = nullptr; } public: template < class F, typename std::enable_if::type>::value, int>::type = 0, typename std::enable_if< #if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && (_MSVC_LANG > 201402)) // std::result_of deprecated in C++17, removed in C++20 std::is_convertible::type, R>::value, #else // std::result_of since C++11 std::is_convertible::type, R>::value, #endif int>::type = 0> function_ref(F &&f) { BindTo(f); // not forward } function_ref(std::nullptr_t) {} function_ref(const function_ref &) noexcept = default; function_ref(function_ref &&) noexcept = default; R operator()(Args... args) const { return invoker_(callable_, std::forward(args)...); } explicit operator bool() const { return invoker_; } }; } // namespace nostd OPENTELEMETRY_END_NAMESPACE