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 /// For technical reasons, TfFunctionRef does not support function pointers;
47 /// only function objects. Internally TfFunctionRef stores a void pointer to
48 /// the function object it's referencing, but C++ does not allow function
49 /// pointers to be cast to void pointers. Supporting this case would increase
50 /// this class's size and add complexity to its implementation. Instead,
51 /// callers may wrap function pointers in lambdas to sidestep the issue.
52 ///
53 /// The advantage over std::function is that TfFunctionRef is lighter-weight.
54 /// Since it is non-owning, it guarantees no heap allocation; a possibility with
55 /// std::function. The cost to call a TfFunctionRef is an indirect function
56 /// call.
57 ///
58 /// For example:
59 ///
60 /// \code
61 ///
62 /// // widgetUtil.h ////////////////////////////////
63 ///
64 /// class WidgetUtil
65 /// {
66 /// template <class WidgetPredicate>
67 /// bool AnyWidgetsMatch(WidgetPredicate const &predicate) {
68 /// TfFunctionRef<bool (Widget const &)> predRef(predicate);
69 /// return _AnyWidgetsMatchImpl(predRef);
70 /// }
71 /// private:
72 /// bool _AnyWidgetsMatchImpl(
73 /// TfFunctionRef<bool (Widget const &)> const &pred);
74 /// };
75 ///
76 /// // widgetUtil.cpp //////////////////////////////
77 ///
78 /// #include "widgetUtil.h"
79 ///
80 /// bool WidgetUtil::_AnyWidgetsMatchImpl(
81 /// TfFunctionRef<bool (Widget const &)> const &pred)
82 /// {
83 /// for (Widget const &widget: GetAllTheWidgets()) {
84 /// if (pred(widget)) {
85 /// return true;
86 /// }
87 /// }
88 /// return false;
89 /// }
90 ///
91 /// \endcode
92 ///
93 /// Here the implementation of _AnyWidgetsMatchImpl is kept out-of-line, callers
94 /// can pass their own function objects for the predicate, there is no heap
95 /// allocation, and the cost to invoke the predicate in the implementation is
96 /// just the cost of calling a function pointer.
97 ///
98 template <class Ret, class... Args>
99 class TfFunctionRef<Ret (Args...)>
100 {
101  // Type trait to detect when an argument is a potentially cv-qualified
102  // TfFunctionRef. This is used to disable the generic constructor and
103  // assignment operator so that TfFunctionRef arguments are copied rather
104  // than forming TfFunctionRefs pointing to TfFunctionRefs.
105  template <typename Fn>
106  using _IsFunctionRef = std::is_same<
107  std::remove_cv_t<std::remove_reference_t<Fn>>, TfFunctionRef>;
108 
109 public:
110  /// Construct with an lvalue callable \p fn.
112  constexpr TfFunctionRef(Fn &fn) noexcept
113  : _fn(static_cast<void const *>(std::addressof(fn)))
114  , _invoke(_InvokeFn<Fn>) {}
115 
116  /// Copy construct from another TfFunctionRef. The constructed
117  /// TfFunctionRef refers to the same callable as \p rhs.
118  TfFunctionRef(TfFunctionRef const &rhs) noexcept = default;
119 
120  /// Assign from another TfFunctionRef. After assignment this object refers
121  /// to the same callable as \p rhs.
122  TfFunctionRef &
123  operator=(TfFunctionRef const &rhs) noexcept = default;
124 
125  /// Assign from an lvalue callable \p fn.
126  template <class Fn>
128  TfFunctionRef &>
129  operator=(Fn &fn) noexcept {
130  *this = TfFunctionRef(fn);
131  return *this;
132  }
133 
134  /// Swap this and \p other. After the swap, this refers to \p other's
135  /// previous callable, and \p other refers to this's previous callable.
136  void swap(TfFunctionRef &other) noexcept {
137  std::swap(_fn, other._fn);
138  std::swap(_invoke, other._invoke);
139  }
140 
141  /// Invoke the callable that this object refers to with \p args.
142  inline Ret operator()(Args... args) const {
143  return _invoke(_fn, std::forward<Args>(args)...);
144  }
145 
146 private:
147  template <class Fn>
148  static Ret _InvokeFn(void const *fn, Args...args) {
149  using FnPtr = typename std::add_pointer<
151  return (*static_cast<FnPtr>(fn))(std::forward<Args>(args)...);
152  }
153 
154  void const *_fn;
155  Ret (*_invoke)(void const *, Args...);
156 };
157 
158 /// Swap \p lhs and \p rhs. Equivalent to lhs.swap(rhs).
159 template <class Sig>
160 inline void
162 {
163  lhs.swap(rhs);
164 }
165 
167 
168 #endif // PXR_BASE_TF_FUNCTION_REF_H
void swap(ArAssetInfo &lhs, ArAssetInfo &rhs)
Definition: assetInfo.h:74
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:1631
GLsizei const GLfloat * value
Definition: glcorearb.h:824
std::enable_if_t<!_IsFunctionRef< Fn >::value, TfFunctionRef & > operator=(Fn &fn) noexcept
Assign from an lvalue callable fn.
Definition: functionRef.h:129
void swap(TfFunctionRef &other) noexcept
Definition: functionRef.h:136
constexpr TfFunctionRef(Fn &fn) noexcept
Construct with an lvalue callable fn.
Definition: functionRef.h:112
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1441
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
**If you just want to fire and args
Definition: thread.h:609
Ret operator()(Args...args) const
Invoke the callable that this object refers to with args.
Definition: functionRef.h:142
type
Definition: core.h:1059