chromium/base/functional/function_ref.h

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_FUNCTIONAL_FUNCTION_REF_H_
#define BASE_FUNCTIONAL_FUNCTION_REF_H_

#include <concepts>
#include <string_view>
#include <type_traits>
#include <utility>

#include "base/functional/bind_internal.h"
#include "base/types/is_instantiation.h"
#include "third_party/abseil-cpp/absl/base/attributes.h"
#include "third_party/abseil-cpp/absl/functional/function_ref.h"

namespace base {

template <typename Signature>
class FunctionRef;

// A non-owning reference to any invocable object (e.g. function pointer, method
// pointer, functor, lambda, et cetera) suitable for use as a type-erased
// argument to ForEach-style functions or other visitor patterns that:
//
// - do not need to copy or take ownership of the argument
// - synchronously call the invocable that was passed as an argument
//
// `base::FunctionRef` makes no heap allocations: it is trivially copyable and
// should be passed by value.
//
// `base::FunctionRef` has no null/empty state: a `base::FunctionRef` is always
// valid to invoke.
//
// The usual lifetime precautions for other non-owning references types (e.g.
// `std::string_view`, `base::span`) also apply to `base::FunctionRef`.
// `base::FunctionRef` should typically be used as an argument; returning a
// `base::FunctionRef` or storing a `base::FunctionRef` as a field is dangerous
// and likely to result in lifetime bugs.
//
// `base::RepeatingCallback` and `base::BindRepeating()` is another common way
// to represent type-erased invocable objects. In contrast, it requires a heap
// allocation and is not trivially copyable. It should be used when there are
// ownership requirements (e.g. partial application of arguments to a function
// stored for asynchronous execution).
//
// Note: `base::FunctionRef` is similar to `absl::FunctionRef<R(Args...)>`, but
// with stricter conversions between function types. Return type conversions are
// allowed (e.g. `int` -> `bool`, `Derived*` -> `Base*`); other than that,
// function parameter types must match exactly, and return values may not be
// silently discarded, e.g. `absl::FunctionRef` allows the following:
//
//   // Silently discards `42`.
//   [] (absl::FunctionRef<void()> r) {
//     r();
//   }([] { return 42; });
//
// But with `base::FunctionRef`:
//
//   // Does not compile!
//   [] (base::FunctionRef<void()> r) {
//     r();
//   }([] { return 42; });
FunctionRef<R (Args...)>;

}  // namespace base

#endif  // BASE_FUNCTIONAL_FUNCTION_REF_H_