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