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
14#include "pxr/base/tf/functionTraits.h"
15#include "pxr/base/tf/pxrTslRobinMap/robin_map.h"
16#include "pxr/base/vt/value.h"
17
18#include "pxr/usd/sdf/predicateExpression.h"
19
20#include <initializer_list>
21#include <memory>
22#include <string>
23#include <vector>
24
25PXR_NAMESPACE_OPEN_SCOPE
26
36
39 struct Param {
41 Param(char const *name) : name(name) {}
42
44 template <class Val>
45 Param(char const *name, Val &&defVal)
46 : name(name), val(std::forward<Val>(defVal)) {}
47
48 std::string name;
49 VtValue val;
50 };
51
53 SdfPredicateParamNamesAndDefaults() : _numDefaults(0) {}
54
57 std::initializer_list<Param> const &params)
58 : _params(params.begin(), params.end())
59 , _numDefaults(_CountDefaults()) {}
60
65 SDF_API
66 bool CheckValidity() const;
67
69 std::vector<Param> const &GetParams() const & {
70 return _params;
71 }
72
74 std::vector<Param> GetParams() const && {
75 return std::move(_params);
76 }
77
79 size_t GetNumDefaults() const {
80 return _numDefaults;
81 }
82
83private:
84 SDF_API
85 size_t _CountDefaults() const;
86
87 std::vector<Param> _params;
88 size_t _numDefaults;
89};
90
91
98{
99public:
100 enum Constancy : char { ConstantOverDescendants, MayVaryOverDescendants };
101
105 : _value(false), _constancy(MayVaryOverDescendants) {}
106
108 explicit SdfPredicateFunctionResult(bool value)
109 : SdfPredicateFunctionResult(value, MayVaryOverDescendants) {}
110
112 SdfPredicateFunctionResult(bool value, Constancy constancy)
113 : _value(value), _constancy(constancy) {}
114
117 return { value, ConstantOverDescendants };
118 }
119
122 return { value, MayVaryOverDescendants };
123 }
124
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
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
156 bool GetValue() const {
157 return _value;
158 }
159
161 Constancy GetConstancy() const {
162 return _constancy;
163 }
164
166 bool IsConstant() const {
167 return GetConstancy() == ConstantOverDescendants;
168 }
169
170#if !defined(doxygen)
171 using UnspecifiedBoolType = bool (SdfPredicateFunctionResult::*);
172#endif
173
175 operator UnspecifiedBoolType() const {
176 return _value ? &SdfPredicateFunctionResult::_value : nullptr;
177 }
178
181 return { !_value, _constancy };
182 }
183
189 _value = other._value;
190 if (_constancy == ConstantOverDescendants &&
191 other._constancy == MayVaryOverDescendants) {
192 _constancy = MayVaryOverDescendants;
193 }
194 }
195
196private:
197 friend bool operator==(SdfPredicateFunctionResult lhs,
199 return lhs._value == rhs._value &&
200 lhs._constancy == rhs._constancy;
201 }
202 friend bool operator!=(SdfPredicateFunctionResult lhs,
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
225template <class DomainType>
227
228// fwd decl
229template <class DomainType>
231
232// fwd decl
233template <class DomainType>
237
243template <class DomainType>
245{
247 SdfLinkPredicateExpression<DomainType>(
248 SdfPredicateExpression const &expr,
249 SdfPredicateLibrary const &lib);
250
252
253public:
256 std::function<SdfPredicateFunctionResult (DomainType const &)>;
257
260
263
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
277
280 if (this != &other) {
281 SdfPredicateLibrary copy(other);
282 *this = std::move(copy);
283 }
284 return *this;
285 }
286
290 template <class Fn>
291 SdfPredicateLibrary &Define(char const *name, Fn &&fn) {
292 return Define(name, std::forward<Fn>(fn), {});
293 }
294
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
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
330private:
331
333 _BindCall(std::string const &name,
334 std::vector<SdfPredicateExpression::FnArg> const &args) const {
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(
426 std::is_convertible<DomainType, DomainArgType>::value, "");
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 =
447 TfMetaApply<TfMetaDecay, TfMetaApply<TfMetaTail, FullParams>>;
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 =
578 std::get<std::tuple_size<Tuple>::value-1>(typedArgs);
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<
603 std::tuple_element_t<std::tuple_size<ParamsTuple>::value-1,
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 =
628 TfMetaApply<TfMetaDecay, TfMetaApply<TfMetaTail, FullParams>>;
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
780PXR_NAMESPACE_CLOSE_SCOPE
781
782#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.
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.
std::function< SdfPredicateFunctionResult(DomainType const &)> PredicateFunction
The type of a bound function, the result of binding passed arguments.
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:960
bool IsEmpty() const
Returns true iff this value is empty.
Definition: value.h:1227
Implementation of a hash map using open-addressing and the robin hood hashing algorithm with backward...
Definition: robin_map.h:96
#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.
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>.