xref: /llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h (revision b037bceef6a40c5c00c1f67cc5a334e2c4e5e041)
1 //===- llvm/ADT/STLFunctionalExtras.h - Extras for <functional> -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains some extension to <functional>.
10 //
11 // No library is required when using these functions.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_ADT_STLFUNCTIONALEXTRAS_H
16 #define LLVM_ADT_STLFUNCTIONALEXTRAS_H
17 
18 #include "llvm/ADT/STLForwardCompat.h"
19 #include "llvm/Support/Compiler.h"
20 
21 #include <cstdint>
22 #include <type_traits>
23 #include <utility>
24 
25 namespace llvm {
26 
27 //===----------------------------------------------------------------------===//
28 //     Extra additions to <functional>
29 //===----------------------------------------------------------------------===//
30 
31 /// An efficient, type-erasing, non-owning reference to a callable. This is
32 /// intended for use as the type of a function parameter that is not used
33 /// after the function in question returns.
34 ///
35 /// This class does not own the callable, so it is not in general safe to store
36 /// a function_ref.
37 template<typename Fn> class function_ref;
38 
39 template <typename Ret, typename... Params>
40 class LLVM_GSL_POINTER function_ref<Ret(Params...)> {
41   Ret (*callback)(intptr_t callable, Params ...params) = nullptr;
42   intptr_t callable;
43 
44   template<typename Callable>
45   static Ret callback_fn(intptr_t callable, Params ...params) {
46     return (*reinterpret_cast<Callable*>(callable))(
47         std::forward<Params>(params)...);
48   }
49 
50 public:
51   function_ref() = default;
52   function_ref(std::nullptr_t) {}
53 
54   template <typename Callable>
55   function_ref(
56       Callable &&callable LLVM_LIFETIME_BOUND,
57       // This is not the copy-constructor.
58       std::enable_if_t<!std::is_same<remove_cvref_t<Callable>,
59                                      function_ref>::value> * = nullptr,
60       // Functor must be callable and return a suitable type.
61       std::enable_if_t<std::is_void<Ret>::value ||
62                        std::is_convertible<decltype(std::declval<Callable>()(
63                                                std::declval<Params>()...)),
64                                            Ret>::value> * = nullptr)
65       : callback(callback_fn<std::remove_reference_t<Callable>>),
66         callable(reinterpret_cast<intptr_t>(&callable)) {}
67 
68   Ret operator()(Params ...params) const {
69     return callback(callable, std::forward<Params>(params)...);
70   }
71 
72   explicit operator bool() const { return callback; }
73 
74   bool operator==(const function_ref<Ret(Params...)> &Other) const {
75     return callable == Other.callable;
76   }
77 };
78 
79 } // end namespace llvm
80 
81 #endif // LLVM_ADT_STLFUNCTIONALEXTRAS_H
82