Loading...
Searching...
No Matches
predicateLibrary.h
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
15#include "pxr/base/tf/functionTraits.h"
16#include "pxr/base/tf/pxrTslRobinMap/robin_map.h"
17#include "pxr/base/vt/value.h"
18
19#include "pxr/usd/sdf/predicateExpression.h"
20
21#include <initializer_list>
22#include <memory>
23#include <string>
24#include <vector>
25
26PXR_NAMESPACE_OPEN_SCOPE
27
37
40 struct Param {
42 Param(char const *name) : name(name) {}
43
45 template <class Val>
46 Param(char const *name, Val &&defVal)
47 : name(name), val(std::forward<Val>(defVal)) {}
48
49 std::string name;
50 VtValue val;
51 };
52
54 SdfPredicateParamNamesAndDefaults() : _numDefaults(0) {}
55
58 std::initializer_list<Param> const &params)
59 : _params(params.begin(), params.end())
60 , _numDefaults(_CountDefaults()) {}
61
66 SDF_API
67 bool CheckValidity() const;
68
70 std::vector<Param> const &GetParams() const & {
71 return _params;
72 }
73
75 std::vector<Param> GetParams() const && {
76 return std::move(_params);
77 }
78
80 size_t GetNumDefaults() const {
81 return _numDefaults;
82 }
83
84private:
85 SDF_API
86 size_t _CountDefaults() const;
87
88 std::vector<Param> _params;
89 size_t _numDefaults;
90};
91
92
99{
100public:
101 enum Constancy : char { ConstantOverDescendants, MayVaryOverDescendants };
102
106 : _value(false), _constancy(MayVaryOverDescendants) {}
107
109 explicit SdfPredicateFunctionResult(bool value)
110 : SdfPredicateFunctionResult(value, MayVaryOverDescendants) {}
111
113 SdfPredicateFunctionResult(bool value, Constancy constancy)
114 : _value(value), _constancy(constancy) {}
115
118 return { value, ConstantOverDescendants };
119 }
120
123 return { value, MayVaryOverDescendants };
124 }
125
134 const bool lv = lhs.GetValue(), rv = rhs.GetValue();
135 const bool lc = lhs.IsConstant(), rc = rhs.IsConstant();
136 return (lc && rc) || (!lv && lc) || (!rv && rc)
137 ? MakeConstant(lv && rv)
138 : MakeVarying(lv && rv);
139 }
140
149 const bool lv = lhs.GetValue(), rv = rhs.GetValue();
150 const bool lc = lhs.IsConstant(), rc = rhs.IsConstant();
151 return (lc && rc) || (lv && lc) || (rv && rc)
152 ? MakeConstant(lv || rv)
153 : MakeVarying(lv || rv);
154 }
155
157 bool GetValue() const {
158 return _value;
159 }
160
162 Constancy GetConstancy() const {
163 return _constancy;
164 }
165
167 bool IsConstant() const {
168 return GetConstancy() == ConstantOverDescendants;
169 }
170
171#if !defined(doxygen)
172 using UnspecifiedBoolType = bool (SdfPredicateFunctionResult::*);
173#endif
174
176 operator UnspecifiedBoolType() const {
177 return _value ? &SdfPredicateFunctionResult::_value : nullptr;
178 }
179
182 return { !_value, _constancy };
183 }
184
190 _value = other._value;
191 if (_constancy == ConstantOverDescendants &&
192 other._constancy == MayVaryOverDescendants) {
193 _constancy = MayVaryOverDescendants;
194 }
195 }
196
197private:
198 friend bool operator==(SdfPredicateFunctionResult lhs,
200 return lhs._value == rhs._value &&
201 lhs._constancy == rhs._constancy;
202 }
203 friend bool operator!=(SdfPredicateFunctionResult lhs,
205 return !(lhs == rhs);
206 }
207
208 friend bool operator==(SdfPredicateFunctionResult pfr, bool rhs) {
209 return pfr._value == rhs;
210 }
211 friend bool operator==(bool lhs, SdfPredicateFunctionResult pfr) {
212 return lhs == pfr._value;
213 }
214 friend bool operator!=(SdfPredicateFunctionResult pfr, bool rhs) {
215 return pfr._value != rhs;
216 }
217 friend bool operator!=(bool lhs, SdfPredicateFunctionResult pfr) {
218 return lhs != pfr._value;
219 }
220
221 bool _value;
222 Constancy _constancy;
223};
224
225// fwd decl
226template <class DomainType>
228
229// fwd decl
230template <class DomainType>
232
233// fwd decl
234template <class DomainType>
238
244template <class DomainType>
246{
249 SdfPredicateExpression const &expr,
250 SdfPredicateLibrary const &lib);
251
253
254public:
257 std::function<SdfPredicateFunctionResult (DomainType const &)>;
258
261
264
267 for (auto iter = other._binders.begin(), end = other._binders.end();
268 iter != end; ++iter) {
269 auto &theseBinders = _binders[iter->first];
270 for (auto const &otherBinder: iter->second) {
271 theseBinders.push_back(otherBinder->Clone());
272 }
273 }
274 }
275
278
281 if (this != &other) {
282 SdfPredicateLibrary copy(other);
283 *this = std::move(copy);
284 }
285 return *this;
286 }
287
291 template <class Fn>
292 SdfPredicateLibrary &Define(char const *name, Fn &&fn) {
293 return Define(name, std::forward<Fn>(fn), {});
294 }
295
300 template <class Fn>
302 Define(std::string const &name, Fn &&fn,
303 NamesAndDefaults const &namesAndDefaults) {
304 // Try to create a new overload binder for 'name'. The main operation a
305 // binder does is, when "linking" a predicate expression, given a
306 // specific set of arguments from the expression, check to see if those
307 // arguments can be bound to 'fn', and if so return a type-erased
308 // callable that invokes fn with those arguments.
309 if (auto obinder = _OverloadBinder<std::decay_t<Fn>>
310 ::TryCreate(std::forward<Fn>(fn), namesAndDefaults)) {
311 _binders[name].push_back(std::move(obinder));
312 }
313 return *this;
314 }
315
322 template <class Fn>
324 DefineBinder(std::string const &name, Fn &&fn) {
325 auto binder = _CustomBinder<
326 std::decay_t<Fn>>::Create(std::forward<Fn>(fn));
327 _binders[name].push_back(std::move(binder));
328 return *this;
329 }
330
331private:
332
334 _BindCall(std::string const &name,
335 std::vector<SdfPredicateExpression::FnArg> const &args) const {
337 auto iter = _binders.find(name);
338 if (iter == _binders.end()) {
339 TF_RUNTIME_ERROR("No registered function '%s'", name.c_str());
340 return ret;
341 }
342 // Run thru optimistically first -- if we fail to bind to any overload,
343 // then produce an error message with all the overload signatures.
344 for (auto i = iter->second.rbegin(),
345 end = iter->second.rend(); i != end; ++i) {
346 ret = (*i)->Bind(args);
347 if (ret) {
348 break;
349 }
350 }
351 return ret;
352 }
353
354 template <class ParamType>
355 static void _CheckOneNameAndDefault(
356 bool &valid, size_t index, size_t numParams,
357 NamesAndDefaults const &namesAndDefaults) {
358
359 // If the namesIndex-th param has a default, it must be convertible to
360 // the ArgIndex-th type.
361 std::vector<NamesAndDefaults::Param> const &
362 params = namesAndDefaults.GetParams();
363
364 size_t nFromEnd = numParams - index - 1;
365 if (nFromEnd >= params.size()) {
366 // No more names & defaults to check.
367 return;
368 }
369
370 size_t namesIndex = params.size() - nFromEnd - 1;
371
372 auto const &param = params[namesIndex];
373 if (!param.val.IsEmpty() && !param.val.CanCast<ParamType>()) {
374 TF_CODING_ERROR("Predicate default parameter '%s' value of "
375 "type '%s' cannot convert to c++ argument of "
376 "type '%s' at index %zu",
377 param.name.c_str(),
378 param.val.GetTypeName().c_str(),
380 index);
381 valid = false;
382 }
383 }
384
385 template <class ParamsTuple, size_t... I>
386 static bool
387 _CheckNamesAndDefaultsImpl(
388 NamesAndDefaults const &namesAndDefaults,
389 std::index_sequence<I...>) {
390 // A fold expression would let us just do &&, but that's c++'17, so we
391 // just do all of them and set a bool.
392 bool valid = true;
393 constexpr size_t N = std::tuple_size<ParamsTuple>::value;
394 // Need an unused array so we can use an initializer list to invoke
395 // _CheckOneNameAndDefault N times.
396 int unused[] = {
397 0,
398 (_CheckOneNameAndDefault<std::tuple_element_t<N-I-1, ParamsTuple>>(
399 valid, N-I-1, N, namesAndDefaults), 0)...
400 };
401 TF_UNUSED(unused);
402 return valid;
403 }
404
405 template <class Fn>
406 static bool
407 _CheckNamesAndDefaultsWithSignature(
408 NamesAndDefaults const &namesAndDefaults) {
409 // Basic check for declared names & defaults.
410 if (!namesAndDefaults.CheckValidity()) {
411 return false;
412 }
413
414 using Traits = TfFunctionTraits<Fn>;
415
416 // Return type must convert to bool.
417 static_assert(
418 std::is_same<typename Traits::ReturnType,
420 std::is_convertible<
421 typename Traits::ReturnType, bool>::value, "");
422
423 // Fn must have at least one argument, and DomainType must be
424 // convertible to the first arg.
425 using DomainArgType = typename Traits::template NthArg<0>;
426 static_assert(
427 std::is_convertible<DomainType, DomainArgType>::value, "");
428
429 // Issue an error if there are more named arguments than c++ function
430 // arguments. Subtract one from Arity to account for the leading
431 // DomainType argument.
432 std::vector<NamesAndDefaults::Param> const &
433 params = namesAndDefaults.GetParams();
434 if (params.size() > Traits::Arity-1) {
435 TF_CODING_ERROR("Predicate named arguments (%zu) exceed number of "
436 "C++ function arguments (%zu)",
437 params.size(), Traits::Arity-1);
438 return false;
439 }
440
441 // Now check the names and defaults against the Fn signature, from back
442 // to front, since namesAndDefaults must be "right-aligned" -- that is,
443 // any unnamed arguments must come first.
444 if (!params.empty()) {
445 // Strip DomainType arg...
446 using FullParams = typename Traits::ArgTypes;
447 using Params =
448 TfMetaApply<TfMetaDecay, TfMetaApply<TfMetaTail, FullParams>>;
449 using ParamsTuple = TfMetaApply<std::tuple, Params>;
450
451 return _CheckNamesAndDefaultsImpl<ParamsTuple>(
452 namesAndDefaults, std::make_index_sequence<Traits::Arity-1> {});
453 }
454 return true;
455 }
456
457 template <class ParamType>
458 static void _TryBindOne(
459 size_t index, size_t numParams,
460 ParamType &param,
461 bool &boundAllParams,
462 std::vector<SdfPredicateExpression::FnArg> const &args,
463 std::vector<bool> &boundArgs,
464 NamesAndDefaults const &namesAndDefaults) {
465
466 // Bind the index-th 'param' from 'args' &
467 // 'namesAndDefaults'. 'boundArgs' corresponds to 'args' and indicates
468 // which have already been bound. This function sets one bit in
469 // 'boundArgs' if it binds one of them to a parameter. It may bind a
470 // default from 'namesAndDefaults', in which case it sets no bit. If no
471 // suitable binding can be determined for this parameter, set
472 // 'boundAllParams' false.
473
474 // If we've already failed to bind, just return early.
475 if (!boundAllParams) {
476 return;
477 }
478
479 // namesAndDefaults covers trailing parameters -- that is, there may be
480 // zero or more leading unnamed parameters.
481 std::vector<NamesAndDefaults::Param> const &
482 params = namesAndDefaults.GetParams();
483 size_t numUnnamed = params.size() - numParams;
484 NamesAndDefaults::Param const *paramNameAndDefault = nullptr;
485 if (index >= numUnnamed) {
486 paramNameAndDefault = &params[index - numUnnamed];
487 }
488
489 // If this is a purely positional parameter (paramNameAndDefault is
490 // nullptr) or the caller supplied a positional arg (unnamed) then we
491 // use index-correspondence.
492 auto const *posArg =
493 (index < args.size() && args[index].argName.empty()) ?
494 &args[index] : nullptr;
495
496 auto tryBind = [&](VtValue const &val, size_t argIndex) {
498 if (!cast.IsEmpty()) {
499 param = cast.UncheckedRemove<ParamType>();
500 boundArgs[argIndex] = true;
501 return true;
502 }
503 boundAllParams = false;
504 return false;
505 };
506
507 if (!paramNameAndDefault) {
508 // If this is a positional parameter, the arg must be too.
509 if (!posArg || !posArg->argName.empty()) {
510 boundAllParams = false;
511 return;
512 }
513 // Try to bind posArg.
514 tryBind(posArg->value, index);
515 return;
516 }
517 else if (posArg) {
518 // Passed a positional arg, try to bind.
519 tryBind(posArg->value, index);
520 return;
521 }
522
523 // Only possibility is a keyword arg. If there's a matching name, try
524 // to bind that, otherwise try to fill a default.
525 for (size_t i = 0, end = args.size(); i != end; ++i) {
526 if (boundArgs[i]) {
527 // Already bound.
528 continue;
529 }
530 if (args[i].argName == paramNameAndDefault->name) {
531 // Matching name -- try to bind.
532 tryBind(args[i].value, i);
533 return;
534 }
535 }
536
537 // No matching arg, try to fill default val.
538 VtValue cast = VtValue::Cast<ParamType>(paramNameAndDefault->val);
539 if (!cast.IsEmpty()) {
540 param = cast.UncheckedRemove<ParamType>();
541 }
542 else {
543 // Error, could not fill default.
544 boundAllParams = false;
545 }
546 }
547
548 template <class ParamsTuple, size_t... I>
549 static bool
550 _TryBindArgs(ParamsTuple &params,
551 std::vector<SdfPredicateExpression::FnArg> const &args,
552 NamesAndDefaults const &namesAndDefaults,
553 std::index_sequence<I...>,
554 std::vector<bool> &boundArgs) {
555
556 // A fold expression would let us just do &&, but that's '17, so we just
557 // do all of them and set a bool.
558 bool bound = true;
559 // vector<bool> bit-packing triggers spurious -Warray-bounds and
560 // -Wstringop-overflow from GCC 13 when its memmove is inlined here.
561 ARCH_PRAGMA_PUSH
562 ARCH_PRAGMA_ARRAY_BOUNDS
563 ARCH_PRAGMA_STRINGOP_OVERFLOW
564 boundArgs.assign(args.size(), false);
565 ARCH_PRAGMA_POP
566 // Need a unused array so we can use an initializer list to invoke
567 // _TryBindOne N times.
568 int unused[] = {
569 0,
570 (_TryBindOne(I, std::tuple_size<ParamsTuple>::value,
571 std::get<I>(params), bound,
572 args, boundArgs, namesAndDefaults), 0)...
573 };
574 TF_UNUSED(unused);
575 return bound;
576 }
577
578 template <class Tuple>
579 static void
580 _FillArbitraryArgs(std::true_type,
581 std::vector<SdfPredicateExpression::FnArg> const &args,
582 std::vector<bool> const &boundArgs,
583 Tuple &typedArgs) {
584 std::vector<SdfPredicateExpression::FnArg> &rest =
585 std::get<std::tuple_size<Tuple>::value-1>(typedArgs);
586 // 'boundArgs' and 'args' correspond. Fill 'rest' with the elements of
587 // 'args' for which the corresponding element of 'boundArgs' is false,
588 // in order.
589 rest.clear();
590 for (size_t i = 0; i != args.size(); ++i) {
591 if (!boundArgs[i]) {
592 rest.push_back(args[i]);
593 }
594 }
595 }
596
597 template <class T>
598 static void
599 _FillArbitraryArgs(std::false_type,
600 std::vector<SdfPredicateExpression::FnArg> const &,
601 std::vector<bool> const &,
602 T const &) {
603 // Do nothing.
604 }
605
606 template <class ParamsTuple>
607 static constexpr bool
608 _TakesArbitraryArgs(std::true_type) { // arity >= 2.
609 return std::is_same<
610 std::tuple_element_t<std::tuple_size<ParamsTuple>::value-1,
611 ParamsTuple>,
612 std::vector<SdfPredicateExpression::FnArg>
613 >::value;
614 }
615
616 template <class ParamsTuple>
617 static constexpr bool
618 _TakesArbitraryArgs(std::false_type) { // arity < 2.
619 return false;
620 }
621
622 template <class Fn>
623 static PredicateFunction
624 _TryToBindCall(Fn const &fn,
625 std::vector<SdfPredicateExpression::FnArg> const &args,
626 NamesAndDefaults const &namesAndDefaults) {
627
628 // We need to determine an argument for each parameter of Fn, then make
629 // a callable object that calls that function.
630
631 // Strip DomainType arg...
632 using Traits = TfFunctionTraits<Fn>;
633 using FullParams = typename Traits::ArgTypes;
634 using Params =
635 TfMetaApply<TfMetaDecay, TfMetaApply<TfMetaTail, FullParams>>;
636 using ParamsTuple = TfMetaApply<std::tuple, Params>;
637
638 // If there are at least two parameters to Fn (first has to be
639 // DomainType) and the last parameter type is vector<FnArg>, then
640 // namesAndDefaults does not apply to it, and any remaining unbound args
641 // after binding are passed through that parameter.
642 static const bool TakesArbitraryArgs =
643 _TakesArbitraryArgs<ParamsTuple>(
644 std::integral_constant<bool, Traits::Arity >= 2> {});
645
646 size_t minArgs = Traits::Arity-1 - namesAndDefaults.GetNumDefaults();
647 size_t maxArgs = TakesArbitraryArgs ? size_t(-1) : Traits::Arity-1;
648
649 // Number of bindable args is arity-1 (for the domain arg) or -2 if the
650 // trailing parameter is the vector<FnArg> bag of extra arguments.
651 static const size_t NumBindableArgs =
652 Traits::Arity - (TakesArbitraryArgs ? 2 : 1);
653
654 if (args.size() < minArgs) {
655 TF_RUNTIME_ERROR("Function requires at least %zu argument%s, "
656 "%zu given", minArgs, minArgs == 1 ? "" : "s",
657 args.size());
658 return {};
659 }
660 if (args.size() > maxArgs) {
661 TF_RUNTIME_ERROR("Function takes at most %zu argument%s, %zu given",
662 maxArgs, maxArgs == 1 ? "" : "s", args.size());
663 return {};
664 }
665
666 ParamsTuple typedArgs;
667 std::vector<bool> boundArgs;
668 if (_TryBindArgs(typedArgs, args, namesAndDefaults,
669 std::make_index_sequence<NumBindableArgs> {},
670 boundArgs)) {
671 _FillArbitraryArgs(
672 std::integral_constant<bool, TakesArbitraryArgs> {},
673 args, boundArgs, typedArgs);
674 return [typedArgs, fn](DomainType const &obj) {
676 std::apply(fn,
677 std::tuple_cat(std::make_tuple(obj), typedArgs))
678 };
679 };
680 }
681 return {};
682 }
683
684 struct _OverloadBinderBase
685 {
686 virtual ~_OverloadBinderBase() = default;
688 Bind(std::vector<SdfPredicateExpression::FnArg> const &args) const {
689 return _Bind(args);
690 }
691 virtual std::unique_ptr<_OverloadBinderBase> Clone() const = 0;
692 protected:
693 _OverloadBinderBase() = default;
694
695 explicit _OverloadBinderBase(NamesAndDefaults const &namesAndDefaults)
696 : _namesAndDefaults(namesAndDefaults) {}
697
698 virtual PredicateFunction
699 _Bind(std::vector<
700 SdfPredicateExpression::FnArg> const &args) const = 0;
701
702 NamesAndDefaults _namesAndDefaults;
703 };
704
705 template <class Fn>
706 struct _OverloadBinder : _OverloadBinderBase
707 {
708 ~_OverloadBinder() override = default;
709
710 static std::unique_ptr<_OverloadBinder>
711 TryCreate(Fn &&fn, NamesAndDefaults const &nd) {
712 auto ret = std::unique_ptr<_OverloadBinder>(
713 new _OverloadBinder(std::move(fn), nd));
714 if (!_CheckNamesAndDefaultsWithSignature<Fn>(nd)) {
715 ret.reset();
716 }
717 return ret;
718 }
719
720 std::unique_ptr<_OverloadBinderBase> Clone() const override {
721 return std::unique_ptr<
722 _OverloadBinder>(new _OverloadBinder(*this));
723 }
724
725 private:
726 _OverloadBinder(_OverloadBinder const &) = default;
727
728 explicit _OverloadBinder(Fn &&fn,
729 NamesAndDefaults const &namesAndDefaults)
730 : _OverloadBinderBase(namesAndDefaults)
731 , _fn(std::move(fn)) {}
732
733 explicit _OverloadBinder(Fn const &fn,
734 NamesAndDefaults const &namesAndDefaults)
735 : _OverloadBinder(Fn(fn), namesAndDefaults) {}
736
738 _Bind(std::vector<
739 SdfPredicateExpression::FnArg> const &args) const override {
740 // Try to bind 'args' to _fn's parameters, taking _namesAndDefaults
741 // into account.
742 return _TryToBindCall(_fn, args, this->_namesAndDefaults);
743 }
744
745 Fn _fn;
746 };
747
748 template <class Fn>
749 struct _CustomBinder : _OverloadBinderBase
750 {
751 ~_CustomBinder() override = default;
752
753 static std::unique_ptr<_CustomBinder>
754 Create(Fn &&fn) {
755 return std::unique_ptr<_CustomBinder>(
756 new _CustomBinder(std::move(fn)));
757 }
758
759 std::unique_ptr<_OverloadBinderBase> Clone() const override {
760 return std::unique_ptr<_CustomBinder>(new _CustomBinder(*this));
761 }
762
763 private:
764 _CustomBinder(_CustomBinder const &) = default;
765 explicit _CustomBinder(Fn &&fn)
766 : _OverloadBinderBase()
767 , _fn(std::move(fn)) {}
768 explicit _CustomBinder(Fn const &fn) : _CustomBinder(Fn(fn)) {}
769
771 _Bind(std::vector<
772 SdfPredicateExpression::FnArg> const &args) const override {
773 // Call _fn to try to bind 'args', producing a callable.
774 return _fn(args);
775 }
776
777 Fn _fn;
778 };
779
780 using _OverloadBinderBasePtr = std::unique_ptr<_OverloadBinderBase>;
781
783 std::string, std::vector<_OverloadBinderBasePtr>
784 > _binders;
785};
786
787PXR_NAMESPACE_CLOSE_SCOPE
788
789#endif // PXR_USD_SDF_PREDICATE_EXPRESSION_EVAL_H
Low-level utilities for informing users of various internal and external diagnostic conditions.
Represents a logical expression syntax tree consisting of predicate function calls joined by the logi...
Represents the result of a predicate function: a pair of the boolean result and a Constancy token ind...
static SdfPredicateFunctionResult Or(SdfPredicateFunctionResult lhs, SdfPredicateFunctionResult rhs)
Return the logical or of lhs and rhs with constancy propagation.
SdfPredicateFunctionResult operator!() const
Return a result with the opposite value but the same constancy.
static SdfPredicateFunctionResult MakeConstant(bool value)
Create with value and 'ConstantOverDescendants'.
void SetAndPropagateConstancy(SdfPredicateFunctionResult other)
Set this result's value to other's value, and propagate constancy; if both this and other are Constan...
static SdfPredicateFunctionResult MakeVarying(bool value)
Create with value and 'MayVaryOverDescendants'.
static SdfPredicateFunctionResult And(SdfPredicateFunctionResult lhs, SdfPredicateFunctionResult rhs)
Return the logical and of lhs and rhs with constancy propagation.
SdfPredicateFunctionResult(bool value)
Construct with value and MayVaryOverDescendants constancy.
SdfPredicateFunctionResult(bool value, Constancy constancy)
Construct with value and constancy.
bool GetValue() const
Return the result value.
bool IsConstant() const
Return true if this result's constancy is ConstantOverDescendants.
Constancy GetConstancy() const
Return the result constancy.
constexpr SdfPredicateFunctionResult()
Default construction produces a 'false' result that 'MayVaryOverDescendants'.
Represents a library of predicate functions for use with SdfPredicateExpression.
std::function< SdfPredicateFunctionResult(DomainType const &)> PredicateFunction
The type of a bound function, the result of binding passed arguments.
SdfPredicateLibrary & Define(std::string const &name, Fn &&fn, NamesAndDefaults const &namesAndDefaults)
Register a function with name name in this library.
SdfPredicateLibrary()=default
Default constructor produces an empty library.
SdfPredicateLibrary & DefineBinder(std::string const &name, Fn &&fn)
Register a custom binding function for name in this library.
SdfPredicateLibrary & Define(char const *name, Fn &&fn)
Register a function with name name in this library.
SdfPredicateLibrary(SdfPredicateLibrary const &other)
Copy-construct from an other library.
SdfPredicateLibrary & operator=(SdfPredicateLibrary &&other)=default
Move-assignment from an other library.
SdfPredicateLibrary & operator=(SdfPredicateLibrary const &other)
Copy-assignment from an other library.
SdfPredicateLibrary(SdfPredicateLibrary &&other)=default
Move-construct from an other library.
friend SdfPredicateProgram< DomainType > SdfLinkPredicateExpression(SdfPredicateExpression const &expr, SdfPredicateLibrary const &lib)
Link expr with lib and return a callable program that evaluates expr on given objects of the DomainTy...
Represents a callable "program", the result of linking an SdfPredicateExpression with an SdfPredicate...
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition value.h:90
T UncheckedRemove()
Make this value empty and return the held T instance.
Definition value.h:1019
VtValue & Cast()
Return this holding value type cast to T.
Definition value.h:1232
bool IsEmpty() const
Returns true iff this value is empty.
Definition value.h:1286
Implementation of a hash map using open-addressing and the robin hood hashing algorithm with backward...
Definition robin_map.h:96
std::string ArchGetDemangled()
Return demangled RTTI generated-type name.
Definition demangle.h:86
#define TF_RUNTIME_ERROR(fmt, args)
Issue a generic runtime error, but continue execution.
Definition diagnostic.h:83
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition diagnostic.h:68
#define TF_UNUSED(x)
Stops compiler from producing unused argument or variable warnings.
Definition tf.h:168
STL namespace.
Pragmas for controlling compiler-specific behaviors.
Represents a function argument name and value.
single named parameter with an optional default value.
Param(char const *name, Val &&defVal)
Construct from name and default value.
Param(char const *name)
Construct with or implicitly convert from name.
Represents named function parameters, with optional default values.
std::vector< Param > GetParams() const &&
Move-return the parameters in a vector.
size_t GetNumDefaults() const
Return the number of params with default values.
SDF_API bool CheckValidity() const
Check that all parameters have non-empty names and that all paramters following the first with a defa...
SdfPredicateParamNamesAndDefaults()
Default constructor produces empty set of names & defaults.
std::vector< Param > const & GetParams() const &
Return a reference to the parameters in a vector.
SdfPredicateParamNamesAndDefaults(std::initializer_list< Param > const &params)
Construct or implicitly convert from initializer_list<Param>.