HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
functionRef.h
Go to the documentation of this file.
1 //
2 // Copyright 2020 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_BASE_TF_FUNCTION_REF_H
25 #define PXR_BASE_TF_FUNCTION_REF_H
26 
27 #include "pxr/pxr.h"
28 
29 #include <memory>
30 #include <type_traits>
31 #include <utility>
32 
34 
35 template <class Sig>
37 
38 /// \class TfFunctionRef
39 ///
40 /// This class provides a non-owning reference to a type-erased callable object
41 /// with a specified signature. This is useful in cases where you want to write
42 /// a function that takes a user-provided callback, and that callback is used
43 /// only in the duration of the function call, and you want to keep your
44 /// function's implementation out-of-line.
45 ///
46 /// The advantage over std::function is that TfFunctionRef is lighter-weight.
47 /// Since it is non-owning, it guarantees no heap allocation; a possibility with
48 /// std::function. The cost to call a TfFunctionRef is an indirect function
49 /// call.
50 ///
51 /// For example:
52 ///
53 /// \code
54 ///
55 /// // widgetUtil.h ////////////////////////////////
56 ///
57 /// class WidgetUtil
58 /// {
59 /// template <class WidgetPredicate>
60 /// bool AnyWidgetsMatch(WidgetPredicate const &predicate) {
61 /// TfFunctionRef<bool (Widget const &)> predRef(predicate);
62 /// return _AnyWidgetsMatchImpl(predRef);
63 /// }
64 /// private:
65 /// bool _AnyWidgetsMatchImpl(
66 /// TfFunctionRef<bool (Widget const &)> const &pred);
67 /// };
68 ///
69 /// // widgetUtil.cpp //////////////////////////////
70 ///
71 /// #include "widgetUtil.h"
72 ///
73 /// bool WidgetUtil::_AnyWidgetsMatchImpl(
74 /// TfFunctionRef<bool (Widget const &)> const &pred)
75 /// {
76 /// for (Widget const &widget: GetAllTheWidgets()) {
77 /// if (pred(widget)) {
78 /// return true;
79 /// }
80 /// }
81 /// return false;
82 /// }
83 ///
84 /// \endcode
85 ///
86 /// Here the implementation of _AnyWidgetsMatchImpl is kept out-of-line, callers
87 /// can pass their own function objects for the predicate, there is no heap
88 /// allocation, and the cost to invoke the predicate in the implementation is
89 /// just the cost of calling a function pointer.
90 ///
91 template <class Ret, class... Args>
92 class TfFunctionRef<Ret (Args...)>
93 {
94 public:
95  /// Construct with an lvalue callable \p fn.
96  template <class Fn>
97  constexpr TfFunctionRef(Fn &fn) noexcept
98  : _fn(static_cast<void const *>(std::addressof(fn)))
99  , _invoke(_InvokeFn<Fn>) {}
100 
101  /// Copy construct from another TfFunctionRef. The constructed
102  /// TfFunctionRef refers to the same callable as \p rhs.
103  TfFunctionRef(TfFunctionRef const &rhs) noexcept = default;
104 
105  /// Assign from another TfFunctionRef. After assignment this object refers
106  /// to the same callable as \p rhs.
107  TfFunctionRef &
108  operator=(TfFunctionRef const &rhs) noexcept = default;
109 
110  /// Assign from an lvalue callable \p fn.
111  template <class Fn>
112  TfFunctionRef &
113  operator=(Fn &fn) noexcept {
114  *this = TfFunctionRef(fn);
115  return *this;
116  }
117 
118  /// Swap this and \p other. After the swap, this refers to \p other's
119  /// previous callable, and \p other refers to this's previous callable.
120  void swap(TfFunctionRef &other) noexcept {
121  std::swap(_fn, other._fn);
122  std::swap(_invoke, other._invoke);
123  }
124 
125  /// Invoke the callable that this object refers to with \p args.
126  inline Ret operator()(Args... args) const {
127  return _invoke(_fn, std::forward<Args>(args)...);
128  }
129 
130 private:
131  template <class Fn>
132  static Ret _InvokeFn(void const *fn, Args...args) {
133  using FnPtr = typename std::add_pointer<
135  return (*static_cast<FnPtr>(fn))(std::forward<Args>(args)...);
136  }
137 
138  void const *_fn;
139  Ret (*_invoke)(void const *, Args...);
140 };
141 
142 /// Swap \p lhs and \p rhs. Equivalent to lhs.swap(rhs).
143 template <class Sig>
144 inline void
146 {
147  lhs.swap(rhs);
148 }
149 
151 
152 #endif // PXR_BASE_TF_FUNCTION_REF_H
void swap(ArAssetInfo &lhs, ArAssetInfo &rhs)
Definition: assetInfo.h:60
const Args & args
Definition: printf.h:628
void swap(UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &a, UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &b)
Definition: UT_ArraySet.h:1629
constexpr TfFunctionRef(Fn &fn) noexcept
Construct with an lvalue callable fn.
Definition: functionRef.h:97
void swap(TfFunctionRef &other) noexcept
Definition: functionRef.h:120
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1346
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
TfFunctionRef & operator=(Fn &fn) noexcept
Assign from an lvalue callable fn.
Definition: functionRef.h:113
Ret operator()(Args...args) const
Invoke the callable that this object refers to with args.
Definition: functionRef.h:126
type
Definition: core.h:528