#ifndef ABSL_FUNCTIONAL_FUNCTION_REF_H_
#define ABSL_FUNCTIONAL_FUNCTION_REF_H_
#include <cassert>
#include <functional>
#include <type_traits>
#include "absl/base/attributes.h"
#include "absl/functional/internal/function_ref.h"
#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
template <typename T>
class FunctionRef;
template <typename R, typename... Args>
class FunctionRef<R(Args...)> {
private:
template <typename F,
typename FR = absl::base_internal::invoke_result_t<F, Args&&...>>
using EnableIfCompatible =
typename std::enable_if<std::is_void<R>::value ||
std::is_convertible<FR, R>::value>::type;
public:
template <typename F, typename = EnableIfCompatible<const F&>>
FunctionRef(const F& f ABSL_ATTRIBUTE_LIFETIME_BOUND)
: invoker_(&absl::functional_internal::InvokeObject<F, R, Args...>) {
absl::functional_internal::AssertNonNull(f);
ptr_.obj = &f;
}
template <
typename F, typename = EnableIfCompatible<F*>,
absl::functional_internal::EnableIf<absl::is_function<F>::value> = 0>
FunctionRef(F* f) : invoker_(&absl::functional_internal::InvokeFunction<F*, R, Args...>) {
assert(f != nullptr);
ptr_.fun = reinterpret_cast<decltype(ptr_.fun)>(f);
}
FunctionRef& operator=(const FunctionRef& rhs) = delete;
FunctionRef(const FunctionRef& rhs) = default;
R operator()(Args... args) const {
return invoker_(ptr_, std::forward<Args>(args)...);
}
private:
absl::functional_internal::VoidPtr ptr_;
absl::functional_internal::Invoker<R, Args...> invoker_;
};
template <typename R, typename... Args>
class FunctionRef<R(Args...) const> : public FunctionRef<R(Args...)> {
public:
using FunctionRef<R(Args...)>::FunctionRef;
};
ABSL_NAMESPACE_END
}
#endif