HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
predicateLibrary.h
Go to the documentation of this file.
1 //
2 // Copyright 2023 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_USD_SDF_PREDICATE_LIBRARY_H
25 #define PXR_USD_SDF_PREDICATE_LIBRARY_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/usd/sdf/api.h"
29 
30 #include "pxr/base/tf/diagnostic.h"
33 #include "pxr/base/vt/value.h"
34 
36 #include "pxr/usd/sdf/invoke.hpp"
37 
38 #include <initializer_list>
39 #include <memory>
40 #include <string>
41 #include <vector>
42 
44 
45 /// \class SdfPredicateParamNamesAndDefaults
46 ///
47 /// Represents named function parameters, with optional default values. These
48 /// are generally constructed via an initializer_list and specified in
49 /// SdfPredicateLibrary::Define().
50 ///
51 /// Valid parameter names and defaults have non-empty names, and all parameters
52 /// following the first one with a default value must also have default values.
54 
55  /// \class Param represents a single named parameter with an optional
56  /// default value.
57  struct Param {
58  /// Construct with or implicitly convert from name.
59  Param(char const *name) : name(name) {}
60 
61  /// Construct from name and default value.
62  template <class Val>
63  Param(char const *name, Val &&defVal)
64  : name(name), val(std::forward<Val>(defVal)) {}
65 
68  };
69 
70  /// Default constructor produces empty set of names & defaults.
71  SdfPredicateParamNamesAndDefaults() : _numDefaults(0) {}
72 
73  /// Construct or implicitly convert from initializer_list<Param>.
75  std::initializer_list<Param> const &params)
76  : _params(params.begin(), params.end())
77  , _numDefaults(_CountDefaults()) {}
78 
79  /// Check that all parameters have non-empty names and that all paramters
80  /// following the first with a default value also have default values.
81  /// Issue TF_CODING_ERROR()s and return false if these conditions are
82  /// violated, otherwise return true.
83  SDF_API
84  bool CheckValidity() const;
85 
86  /// Return a reference to the parameters in a vector.
87  std::vector<Param> const &GetParams() const & {
88  return _params;
89  }
90 
91  /// Move-return the parameters in a vector.
92  std::vector<Param> GetParams() const && {
93  return std::move(_params);
94  }
95 
96  /// Return the number of params with default values.
97  size_t GetNumDefaults() const {
98  return _numDefaults;
99  }
100 
101 private:
102  SDF_API
103  size_t _CountDefaults() const;
104 
105  std::vector<Param> _params;
106  size_t _numDefaults;
107 };
108 
109 
110 /// \class SdfPredicateFunctionResult
111 ///
112 /// Represents the result of a predicate function: a pair of the boolean result
113 /// and a Constancy token indicating whether the function result is constant
114 /// over "descendant" objects, or that it might vary over "descendant" objects.
116 {
117 public:
119 
120  /// Default construction produces a 'false' result that
121  /// 'MayVaryOverDescendants'.
123  : _value(false), _constancy(MayVaryOverDescendants) {}
124 
125  /// Construct with \p value and \p MayVaryOverDescendants constancy.
128 
129  /// Construct with \p value and \p constancy.
131  : _value(value), _constancy(constancy) {}
132 
133  /// Create with \p value and 'ConstantOverDescendants'
135  return { value, ConstantOverDescendants };
136  }
137 
138  /// Create with \p value and 'MayVaryOverDescendants'
140  return { value, MayVaryOverDescendants };
141  }
142 
143  /// Return the result value.
144  bool GetValue() const {
145  return _value;
146  }
147 
148  /// Return the result constancy.
150  return _constancy;
151  }
152 
153  /// Return true if this result's constancy is ConstantOverDescendants.
154  bool IsConstant() const {
156  }
157 
158 #if !defined(doxygen)
160 #endif //!doxygen
161 
162  /// Return GetValue().
163  operator UnspecifiedBoolType() const {
164  return _value ? &SdfPredicateFunctionResult::_value : nullptr;
165  }
166 
167  /// Return a result with the opposite value but the same constancy.
169  return { !_value, _constancy };
170  }
171 
172  /// Set this result's value to \p other's value, and propagate constancy; if
173  /// both this and \p other are ConstantOverDescendants, this object's
174  /// constancy remains ConstantOverDescendants. Otherwise set this object's
175  /// constancy to MayVaryOverDescendants.
177  _value = other._value;
178  if (_constancy == ConstantOverDescendants &&
179  other._constancy == MayVaryOverDescendants) {
180  _constancy = MayVaryOverDescendants;
181  }
182  }
183 
184 private:
187  return lhs._value == rhs._value &&
188  lhs._constancy == rhs._constancy;
189  }
192  return !(lhs == rhs);
193  }
194 
195  friend bool operator==(SdfPredicateFunctionResult pfr, bool rhs) {
196  return pfr._value == rhs;
197  }
198  friend bool operator==(bool lhs, SdfPredicateFunctionResult pfr) {
199  return lhs == pfr._value;
200  }
201  friend bool operator!=(SdfPredicateFunctionResult pfr, bool rhs) {
202  return pfr._value != rhs;
203  }
204  friend bool operator!=(bool lhs, SdfPredicateFunctionResult pfr) {
205  return lhs != pfr._value;
206  }
207 
208  bool _value;
209  Constancy _constancy;
210 };
211 
212 // fwd decl
213 template <class DomainType>
215 
216 // fwd decl
217 template <class DomainType>
219 
220 // fwd decl
221 template <class DomainType>
225 
226 /// \class SdfPredicateLibrary
227 ///
228 /// Represents a library of predicate functions for use with
229 /// SdfPredicateExpression. Call SdfLinkPredicateExpression() with an
230 /// expression and a library to produce a callable SdfPredicateProgram.
231 template <class DomainType>
233 {
235  SdfLinkPredicateExpression<DomainType>(
236  SdfPredicateExpression const &expr,
237  SdfPredicateLibrary const &lib);
238 
240 
241 public:
242  /// The type of a bound function, the result of binding passed arguments.
243  using PredicateFunction =
244  std::function<SdfPredicateFunctionResult (DomainType const &)>;
245 
246  /// Default constructor produces an empty library.
247  SdfPredicateLibrary() = default;
248 
249  /// Move-construct from an \p other library.
250  SdfPredicateLibrary(SdfPredicateLibrary &&other) = default;
251 
252  /// Copy-construct from an \p other library.
254  for (auto iter = other._binders.begin(), end = other._binders.end();
255  iter != end; ++iter) {
256  auto &theseBinders = _binders[iter->first];
257  for (auto const &otherBinder: iter->second) {
258  theseBinders.push_back(otherBinder->Clone());
259  }
260  }
261  }
262 
263  /// Move-assignment from an \p other library.
265 
266  /// Copy-assignment from an \p other library.
268  if (this != &other) {
269  SdfPredicateLibrary copy(other);
270  *this = std::move(copy);
271  }
272  return *this;
273  }
274 
275  /// Register a function with name \p name in this library. The first
276  /// argument must accept a DomainType instance. The remaining arguments
277  /// must be convertible from bool, int, float, string.
278  template <class Fn>
279  SdfPredicateLibrary &Define(char const *name, Fn &&fn) {
280  return Define(name, std::forward<Fn>(fn), {});
281  }
282 
283  /// Register a function with name \p name in this library. The first
284  /// argument must accept a DomainType instance. The remaining arguments
285  /// must be convertible from bool, int, float, string. Optional parameter
286  /// names and default values may be supplied in \p namesAndDefaults.
287  template <class Fn>
289  Define(std::string const &name, Fn &&fn,
290  NamesAndDefaults const &namesAndDefaults) {
291  // Try to create a new overload binder for 'name'. The main operation a
292  // binder does is, when "linking" a predicate expression, given a
293  // specific set of arguments from the expression, check to see if those
294  // arguments can be bound to 'fn', and if so return a type-erased
295  // callable that invokes fn with those arguments.
296  if (auto obinder = _OverloadBinder<std::decay_t<Fn>>
297  ::TryCreate(std::forward<Fn>(fn), namesAndDefaults)) {
298  _binders[name].push_back(std::move(obinder));
299  }
300  return *this;
301  }
302 
303  /// Register a custom binding function for \p name in this library. The
304  /// function must take a single argument of type
305  /// std::vector<SdfPredicateExpression::FnArg>. When invoked, it must
306  /// attempt to bind the arguments passed in the vector and return a bound
307  /// PredicateFunction object. If the arguments are invalid, return an empty
308  /// PredicateFunction.
309  template <class Fn>
311  DefineBinder(std::string const &name, Fn &&fn) {
312  auto binder = _CustomBinder<
313  std::decay_t<Fn>>::Create(std::forward<Fn>(fn));
314  _binders[name].push_back(std::move(binder));
315  return *this;
316  }
317 
318 private:
319 
321  _BindCall(std::string const &name,
322  std::vector<SdfPredicateExpression::FnArg> const &args) const {
323  PredicateFunction ret;
324  auto iter = _binders.find(name);
325  if (iter == _binders.end()) {
326  TF_RUNTIME_ERROR("No registered function '%s'", name.c_str());
327  return ret;
328  }
329  // Run thru optimistically first -- if we fail to bind to any overload,
330  // then produce an error message with all the overload signatures.
331  for (auto i = iter->second.rbegin(),
332  end = iter->second.rend(); i != end; ++i) {
333  ret = (*i)->Bind(args);
334  if (ret) {
335  break;
336  }
337  }
338  return ret;
339  }
340 
341  template <class ParamType>
342  static void _CheckOneNameAndDefault(
343  bool &valid, size_t index, size_t numParams,
344  NamesAndDefaults const &namesAndDefaults) {
345 
346  // If the namesIndex-th param has a default, it must be convertible to
347  // the ArgIndex-th type.
348  std::vector<NamesAndDefaults::Param> const &
349  params = namesAndDefaults.GetParams();
350 
351  size_t nFromEnd = numParams - index - 1;
352  if (nFromEnd >= params.size()) {
353  // No more names & defaults to check.
354  return;
355  }
356 
357  size_t namesIndex = params.size() - nFromEnd - 1;
358 
359  auto const &param = params[namesIndex];
360  if (!param.val.IsEmpty() && !param.val.CanCast<ParamType>()) {
361  TF_CODING_ERROR("Predicate default parameter '%s' value of "
362  "type '%s' cannot convert to c++ argument of "
363  "type '%s' at index %zu",
364  param.name.c_str(),
365  param.val.GetTypeName().c_str(),
366  ArchGetDemangled<ParamType>().c_str(),
367  index);
368  valid = false;
369  }
370  }
371 
372  template <class ParamsTuple, size_t... I>
373  static bool
374  _CheckNamesAndDefaultsImpl(
375  NamesAndDefaults const &namesAndDefaults,
376  std::index_sequence<I...>) {
377  // A fold expression would let us just do &&, but that's c++'17, so we
378  // just do all of them and set a bool.
379  bool valid = true;
380  constexpr size_t N = std::tuple_size<ParamsTuple>::value;
381  // Need an unused array so we can use an initializer list to invoke
382  // _CheckOneNameAndDefault N times.
383  int unused[] = {
384  0,
385  (_CheckOneNameAndDefault<std::tuple_element_t<N-I-1, ParamsTuple>>(
386  valid, N-I-1, N, namesAndDefaults), 0)...
387  };
388  TF_UNUSED(unused);
389  return valid;
390  }
391 
392  template <class Fn>
393  static bool
394  _CheckNamesAndDefaultsWithSignature(
395  NamesAndDefaults const &namesAndDefaults) {
396  // Basic check for declared names & defaults.
397  if (!namesAndDefaults.CheckValidity()) {
398  return false;
399  }
400 
401  using Traits = TfFunctionTraits<Fn>;
402 
403  // Return type must convert to bool.
404  static_assert(
405  std::is_same<typename Traits::ReturnType,
407  std::is_convertible<
408  typename Traits::ReturnType, bool>::value, "");
409 
410  // Fn must have at least one argument, and DomainType must be
411  // convertible to the first arg.
412  using DomainArgType = typename Traits::template NthArg<0>;
413  static_assert(
415 
416  // Issue an error if there are more named arguments than c++ function
417  // arguments. Subtract one from Arity to account for the leading
418  // DomainType argument.
419  std::vector<NamesAndDefaults::Param> const &
420  params = namesAndDefaults.GetParams();
421  if (params.size() > Traits::Arity-1) {
422  TF_CODING_ERROR("Predicate named arguments (%zu) exceed number of "
423  "C++ function arguments (%zu)",
424  params.size(), Traits::Arity-1);
425  return false;
426  }
427 
428  // Now check the names and defaults against the Fn signature, from back
429  // to front, since namesAndDefaults must be "right-aligned" -- that is,
430  // any unnamed arguments must come first.
431  if (!params.empty()) {
432  // Strip DomainType arg...
433  using FullParams = typename Traits::ArgTypes;
434  using Params =
436  using ParamsTuple = TfMetaApply<std::tuple, Params>;
437 
438  return _CheckNamesAndDefaultsImpl<ParamsTuple>(
439  namesAndDefaults, std::make_index_sequence<Traits::Arity-1> {});
440  }
441  return true;
442  }
443 
444  template <class ParamType>
445  static void _TryBindOne(
446  size_t index, size_t numParams,
447  ParamType &param,
448  bool &boundAllParams,
449  std::vector<SdfPredicateExpression::FnArg> const &args,
450  std::vector<bool> &boundArgs,
451  NamesAndDefaults const &namesAndDefaults) {
452 
453  // Bind the index-th 'param' from 'args' &
454  // 'namesAndDefaults'. 'boundArgs' corresponds to 'args' and indicates
455  // which have already been bound. This function sets one bit in
456  // 'boundArgs' if it binds one of them to a parameter. It may bind a
457  // default from 'namesAndDefaults', in which case it sets no bit. If no
458  // suitable binding can be determined for this parameter, set
459  // 'boundAllParams' false.
460 
461  // If we've already failed to bind, just return early.
462  if (!boundAllParams) {
463  return;
464  }
465 
466  // namesAndDefaults covers trailing parameters -- that is, there may be
467  // zero or more leading unnamed parameters.
468  std::vector<NamesAndDefaults::Param> const &
469  params = namesAndDefaults.GetParams();
470  size_t numUnnamed = params.size() - numParams;
471  NamesAndDefaults::Param const *paramNameAndDefault = nullptr;
472  if (index >= numUnnamed) {
473  paramNameAndDefault = &params[index - numUnnamed];
474  }
475 
476  // If this is a purely positional parameter (paramNameAndDefault is
477  // nullptr) or the caller supplied a positional arg (unnamed) then we
478  // use index-correspondence.
479  auto const *posArg =
480  (index < args.size() && args[index].argName.empty()) ?
481  &args[index] : nullptr;
482 
483  auto tryBind = [&](VtValue const &val, size_t argIndex) {
484  VtValue cast = VtValue::Cast<ParamType>(val);
485  if (!cast.IsEmpty()) {
486  param = cast.UncheckedRemove<ParamType>();
487  boundArgs[argIndex] = true;
488  return true;
489  }
490  boundAllParams = false;
491  return false;
492  };
493 
494  if (!paramNameAndDefault) {
495  // If this is a positional parameter, the arg must be too.
496  if (!posArg || !posArg->argName.empty()) {
497  boundAllParams = false;
498  return;
499  }
500  // Try to bind posArg.
501  tryBind(posArg->value, index);
502  return;
503  }
504  else if (posArg) {
505  // Passed a positional arg, try to bind.
506  tryBind(posArg->value, index);
507  return;
508  }
509 
510  // Only possibility is a keyword arg. If there's a matching name, try
511  // to bind that, otherwise try to fill a default.
512  for (size_t i = 0, end = args.size(); i != end; ++i) {
513  if (boundArgs[i]) {
514  // Already bound.
515  continue;
516  }
517  if (args[i].argName == paramNameAndDefault->name) {
518  // Matching name -- try to bind.
519  tryBind(args[i].value, i);
520  return;
521  }
522  }
523 
524  // No matching arg, try to fill default val.
525  VtValue cast = VtValue::Cast<ParamType>(paramNameAndDefault->val);
526  if (!cast.IsEmpty()) {
527  param = cast.UncheckedRemove<ParamType>();
528  }
529  else {
530  // Error, could not fill default.
531  boundAllParams = false;
532  }
533  }
534 
535  template <class ParamsTuple, size_t... I>
536  static bool
537  _TryBindArgs(ParamsTuple &params,
538  std::vector<SdfPredicateExpression::FnArg> const &args,
539  NamesAndDefaults const &namesAndDefaults,
540  std::index_sequence<I...>,
541  std::vector<bool> &boundArgs) {
542 
543  // A fold expression would let us just do &&, but that's '17, so we just
544  // do all of them and set a bool.
545  bool bound = true;
546  boundArgs.assign(args.size(), false);
547  // Need a unused array so we can use an initializer list to invoke
548  // _TryBindOne N times.
549  int unused[] = {
550  0,
551  (_TryBindOne(I, std::tuple_size<ParamsTuple>::value,
552  std::get<I>(params), bound,
553  args, boundArgs, namesAndDefaults), 0)...
554  };
555  TF_UNUSED(unused);
556  return bound;
557  }
558 
559  template <class Tuple>
560  static void
561  _FillArbitraryArgs(std::true_type,
562  std::vector<SdfPredicateExpression::FnArg> const &args,
563  std::vector<bool> const &boundArgs,
564  Tuple &typedArgs) {
565  std::vector<SdfPredicateExpression::FnArg> &rest =
567  // 'boundArgs' and 'args' correspond. Fill 'rest' with the elements of
568  // 'args' for which the corresponding element of 'boundArgs' is false,
569  // in order.
570  rest.clear();
571  for (size_t i = 0; i != args.size(); ++i) {
572  if (!boundArgs[i]) {
573  rest.push_back(args[i]);
574  }
575  }
576  }
577 
578  template <class T>
579  static void
580  _FillArbitraryArgs(std::false_type,
581  std::vector<SdfPredicateExpression::FnArg> const &,
582  std::vector<bool> const &,
583  T const &) {
584  // Do nothing.
585  }
586 
587  template <class ParamsTuple>
588  static constexpr bool
589  _TakesArbitraryArgs(std::true_type) { // arity >= 2.
590  return std::is_same<
592  ParamsTuple>,
593  std::vector<SdfPredicateExpression::FnArg>
594  >::value;
595  }
596 
597  template <class ParamsTuple>
598  static constexpr bool
599  _TakesArbitraryArgs(std::false_type) { // arity < 2.
600  return false;
601  }
602 
603  template <class Fn>
604  static PredicateFunction
605  _TryToBindCall(Fn const &fn,
606  std::vector<SdfPredicateExpression::FnArg> const &args,
607  NamesAndDefaults const &namesAndDefaults) {
608 
609  // We need to determine an argument for each parameter of Fn, then make
610  // a callable object that calls that function.
611 
612  // Strip DomainType arg...
613  using Traits = TfFunctionTraits<Fn>;
614  using FullParams = typename Traits::ArgTypes;
615  using Params =
617  using ParamsTuple = TfMetaApply<std::tuple, Params>;
618 
619  // If there are at least two parameters to Fn (first has to be
620  // DomainType) and the last parameter type is vector<FnArg>, then
621  // namesAndDefaults does not apply to it, and any remaining unbound args
622  // after binding are passed through that parameter.
623  static const bool TakesArbitraryArgs =
624  _TakesArbitraryArgs<ParamsTuple>(
625  std::integral_constant<bool, Traits::Arity >= 2> {});
626 
627  size_t minArgs = Traits::Arity-1 - namesAndDefaults.GetNumDefaults();
628  size_t maxArgs = TakesArbitraryArgs ? size_t(-1) : Traits::Arity-1;
629 
630  // Number of bindable args is arity-1 (for the domain arg) or -2 if the
631  // trailing parameter is the vector<FnArg> bag of extra arguments.
632  static const size_t NumBindableArgs =
633  Traits::Arity - (TakesArbitraryArgs ? 2 : 1);
634 
635  if (args.size() < minArgs) {
636  TF_RUNTIME_ERROR("Function requires at least %zu argument%s, "
637  "%zu given", minArgs, minArgs == 1 ? "" : "s",
638  args.size());
639  return {};
640  }
641  if (args.size() > maxArgs) {
642  TF_RUNTIME_ERROR("Function takes at most %zu argument%s, %zu given",
643  maxArgs, maxArgs == 1 ? "" : "s", args.size());
644  return {};
645  }
646 
647  ParamsTuple typedArgs;
648  std::vector<bool> boundArgs;
649  if (_TryBindArgs(typedArgs, args, namesAndDefaults,
650  std::make_index_sequence<NumBindableArgs> {},
651  boundArgs)) {
652  _FillArbitraryArgs(
653  std::integral_constant<bool, TakesArbitraryArgs> {},
654  args, boundArgs, typedArgs);
655  return [typedArgs, fn](DomainType const &obj) {
656  // invoke fn with obj & typedArgs. (std::apply in '17).
658  invoke_hpp::apply(fn, std::tuple_cat(
659  std::make_tuple(obj), typedArgs))
660  };
661  };
662  }
663  return {};
664  }
665 
666  struct _OverloadBinderBase
667  {
668  virtual ~_OverloadBinderBase() = default;
670  Bind(std::vector<SdfPredicateExpression::FnArg> const &args) const {
671  return _Bind(args);
672  }
673  virtual std::unique_ptr<_OverloadBinderBase> Clone() const = 0;
674  protected:
675  _OverloadBinderBase() = default;
676 
677  explicit _OverloadBinderBase(NamesAndDefaults const &namesAndDefaults)
678  : _namesAndDefaults(namesAndDefaults) {}
679 
680  virtual PredicateFunction
681  _Bind(std::vector<
682  SdfPredicateExpression::FnArg> const &args) const = 0;
683 
684  NamesAndDefaults _namesAndDefaults;
685  };
686 
687  template <class Fn>
688  struct _OverloadBinder : _OverloadBinderBase
689  {
690  ~_OverloadBinder() override = default;
691 
692  static std::unique_ptr<_OverloadBinder>
693  TryCreate(Fn &&fn, NamesAndDefaults const &nd) {
694  auto ret = std::unique_ptr<_OverloadBinder>(
695  new _OverloadBinder(std::move(fn), nd));
696  if (!_CheckNamesAndDefaultsWithSignature<Fn>(nd)) {
697  ret.reset();
698  }
699  return ret;
700  }
701 
702  std::unique_ptr<_OverloadBinderBase> Clone() const override {
703  return std::unique_ptr<
704  _OverloadBinder>(new _OverloadBinder(*this));
705  }
706 
707  private:
708  _OverloadBinder(_OverloadBinder const &) = default;
709 
710  explicit _OverloadBinder(Fn &&fn,
711  NamesAndDefaults const &namesAndDefaults)
712  : _OverloadBinderBase(namesAndDefaults)
713  , _fn(std::move(fn)) {}
714 
715  explicit _OverloadBinder(Fn const &fn,
716  NamesAndDefaults const &namesAndDefaults)
717  : _OverloadBinder(Fn(fn), namesAndDefaults) {}
718 
720  _Bind(std::vector<
721  SdfPredicateExpression::FnArg> const &args) const override {
722  // Try to bind 'args' to _fn's parameters, taking _namesAndDefaults
723  // into account.
724  return _TryToBindCall(_fn, args, this->_namesAndDefaults);
725  }
726 
727  Fn _fn;
728  };
729 
730  template <class Fn>
731  struct _CustomBinder : _OverloadBinderBase
732  {
733  ~_CustomBinder() override = default;
734 
735  static std::unique_ptr<_CustomBinder>
736  Create(Fn &&fn) {
737  return std::unique_ptr<_CustomBinder>(
738  new _CustomBinder(std::move(fn)));
739  }
740 
741  std::unique_ptr<_OverloadBinderBase> Clone() const override {
742  return std::unique_ptr<_CustomBinder>(new _CustomBinder(*this));
743  }
744 
745  private:
746  _CustomBinder(_CustomBinder const &) = default;
747  explicit _CustomBinder(Fn &&fn)
748  : _OverloadBinderBase()
749  , _fn(std::move(fn)) {}
750  explicit _CustomBinder(Fn const &fn) : _CustomBinder(Fn(fn)) {}
751 
753  _Bind(std::vector<
754  SdfPredicateExpression::FnArg> const &args) const override {
755  // Call _fn to try to bind 'args', producing a callable.
756  return _fn(args);
757  }
758 
759  Fn _fn;
760  };
761 
762  using _OverloadBinderBasePtr = std::unique_ptr<_OverloadBinderBase>;
763 
765  std::string, std::vector<_OverloadBinderBasePtr>
766  > _binders;
767 };
768 
770 
771 #endif // PXR_USD_SDF_PREDICATE_EXPRESSION_EVAL_H
std::vector< Param > GetParams() const &&
Move-return the parameters in a vector.
iterator end() noexcept
Definition: robin_map.h:222
friend bool operator==(SdfPredicateFunctionResult pfr, bool rhs)
Param(char const *name, Val &&defVal)
Construct from name and default value.
bool GetValue() const
Return the result value.
SdfPredicateProgram< DomainType > SdfLinkPredicateExpression(SdfPredicateExpression const &expr, SdfPredicateLibrary< DomainType > const &lib)
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
GLsizei const GLfloat * value
Definition: glcorearb.h:824
#define TF_CODING_ERROR
Param(char const *name)
Construct with or implicitly convert from name.
SdfPredicateLibrary & Define(char const *name, Fn &&fn)
bool IsConstant() const
Return true if this result's constancy is ConstantOverDescendants.
bool IsEmpty() const
Returns true iff this value is empty.
Definition: value.h:1300
GLenum const GLfloat * params
Definition: glcorearb.h:105
friend bool operator==(bool lhs, SdfPredicateFunctionResult pfr)
std::decay_t< decltype(make_index_sequence_impl< N >())> make_index_sequence
Definition: Types.h:234
iterator find(const Key &key)
Definition: robin_map.h:493
SdfPredicateFunctionResult operator!() const
Return a result with the opposite value but the same constancy.
#define TF_RUNTIME_ERROR
SdfPredicateFunctionResult(bool value, Constancy constancy)
Construct with value and constancy.
void SetAndPropagateConstancy(SdfPredicateFunctionResult other)
SYS_FORCE_INLINE const X * cast(const InstancablePtr *o)
static SdfPredicateFunctionResult MakeConstant(bool value)
Create with value and 'ConstantOverDescendants'.
Constancy GetConstancy() const
Return the result constancy.
GLuint GLuint end
Definition: glcorearb.h:475
static SdfPredicateFunctionResult MakeVarying(bool value)
Create with value and 'MayVaryOverDescendants'.
T UncheckedRemove()
Definition: value.h:1041
friend bool operator!=(bool lhs, SdfPredicateFunctionResult pfr)
friend bool operator!=(SdfPredicateFunctionResult lhs, SdfPredicateFunctionResult rhs)
GLuint const GLchar * name
Definition: glcorearb.h:786
SdfPredicateLibrary & operator=(SdfPredicateLibrary const &other)
Copy-assignment from an other library.
friend bool operator==(SdfPredicateFunctionResult lhs, SdfPredicateFunctionResult rhs)
bool(SdfPredicateFunctionResult::*) UnspecifiedBoolType
std::function< SdfPredicateFunctionResult(DomainType const &)> PredicateFunction
The type of a bound function, the result of binding passed arguments.
SdfPredicateLibrary(SdfPredicateLibrary const &other)
Copy-construct from an other library.
SdfPredicateLibrary & DefineBinder(std::string const &name, Fn &&fn)
#define SDF_API
Definition: api.h:40
GLenum GLfloat param
Definition: glcorearb.h:104
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1432
SDF_API bool CheckValidity() const
GLuint index
Definition: glcorearb.h:786
#define TF_UNUSED(x)
Definition: tf.h:185
GLuint GLfloat * val
Definition: glcorearb.h:1608
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
std::vector< Param > const & GetParams() const &
Return a reference to the parameters in a vector.
GA_API const UT_StringHolder N
**If you just want to fire and args
Definition: thread.h:609
SdfPredicateLibrary & operator=(SdfPredicateLibrary &&other)=default
Move-assignment from an other library.
Definition: core.h:1131
SdfPredicateLibrary & Define(std::string const &name, Fn &&fn, NamesAndDefaults const &namesAndDefaults)
size_t GetNumDefaults() const
Return the number of params with default values.
SdfPredicateParamNamesAndDefaults()
Default constructor produces empty set of names & defaults.
typename Tf_GetFuncSig< Fn >::Type TfFunctionTraits
iterator begin() noexcept
Definition: robin_map.h:218
GA_API const UT_StringHolder rest
SdfPredicateFunctionResult(bool value)
Construct with value and MayVaryOverDescendants constancy.
Definition: value.h:164
SdfPredicateLibrary()=default
Default constructor produces an empty library.
friend bool operator!=(SdfPredicateFunctionResult pfr, bool rhs)
typename Tf_MetaApplyImpl< Cls, TypeList >::Type TfMetaApply
Definition: meta.h:53
SdfPredicateParamNamesAndDefaults(std::initializer_list< Param > const &params)
Construct or implicitly convert from initializer_list<Param>.
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:558