Loading...
Searching...
No Matches
predicateLibrary.h
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
31#include "pxr/base/tf/functionTraits.h"
32#include "pxr/base/tf/pxrTslRobinMap/robin_map.h"
33#include "pxr/base/vt/value.h"
34
35#include "pxr/usd/sdf/predicateExpression.h"
36#include "pxr/usd/sdf/invoke.hpp"
37
38#include <initializer_list>
39#include <memory>
40#include <string>
41#include <vector>
42
43PXR_NAMESPACE_OPEN_SCOPE
44
54
57 struct Param {
59 Param(char const *name) : name(name) {}
60
62 template <class Val>
63 Param(char const *name, Val &&defVal)
64 : name(name), val(std::forward<Val>(defVal)) {}
65
66 std::string name;
67 VtValue val;
68 };
69
71 SdfPredicateParamNamesAndDefaults() : _numDefaults(0) {}
72
75 std::initializer_list<Param> const &params)
76 : _params(params.begin(), params.end())
77 , _numDefaults(_CountDefaults()) {}
78
83 SDF_API
84 bool CheckValidity() const;
85
87 std::vector<Param> const &GetParams() const & {
88 return _params;
89 }
90
92 std::vector<Param> GetParams() const && {
93 return std::move(_params);
94 }
95
97 size_t GetNumDefaults() const {
98 return _numDefaults;
99 }
100
101private:
102 SDF_API
103 size_t _CountDefaults() const;
104
105 std::vector<Param> _params;
106 size_t _numDefaults;
107};
108
109
116{
117public:
118 enum Constancy { ConstantOverDescendants, MayVaryOverDescendants };
119
123 : _value(false), _constancy(MayVaryOverDescendants) {}
124
126 explicit SdfPredicateFunctionResult(bool value)
127 : SdfPredicateFunctionResult(value, MayVaryOverDescendants) {}
128
130 SdfPredicateFunctionResult(bool value, Constancy constancy)
131 : _value(value), _constancy(constancy) {}
132
135 return { value, ConstantOverDescendants };
136 }
137
140 return { value, MayVaryOverDescendants };
141 }
142
144 bool GetValue() const {
145 return _value;
146 }
147
149 Constancy GetConstancy() const {
150 return _constancy;
151 }
152
154 bool IsConstant() const {
155 return GetConstancy() == ConstantOverDescendants;
156 }
157
158#if !defined(doxygen)
159 using UnspecifiedBoolType = bool (SdfPredicateFunctionResult::*);
160#endif
161
163 operator UnspecifiedBoolType() const {
164 return _value ? &SdfPredicateFunctionResult::_value : nullptr;
165 }
166
169 return { !_value, _constancy };
170 }
171
177 _value = other._value;
178 if (_constancy == ConstantOverDescendants &&
179 other._constancy == MayVaryOverDescendants) {
180 _constancy = MayVaryOverDescendants;
181 }
182 }
183
184private:
185 friend bool operator==(SdfPredicateFunctionResult lhs,
187 return lhs._value == rhs._value &&
188 lhs._constancy == rhs._constancy;
189 }
190 friend bool operator!=(SdfPredicateFunctionResult lhs,
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
213template <class DomainType>
215
216// fwd decl
217template <class DomainType>
219
220// fwd decl
221template <class DomainType>
225
231template <class DomainType>
233{
235 SdfLinkPredicateExpression<DomainType>(
236 SdfPredicateExpression const &expr,
237 SdfPredicateLibrary const &lib);
238
240
241public:
244 std::function<SdfPredicateFunctionResult (DomainType const &)>;
245
248
251
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
265
268 if (this != &other) {
269 SdfPredicateLibrary copy(other);
270 *this = std::move(copy);
271 }
272 return *this;
273 }
274
278 template <class Fn>
279 SdfPredicateLibrary &Define(char const *name, Fn &&fn) {
280 return Define(name, std::forward<Fn>(fn), {});
281 }
282
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
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
318private:
319
321 _BindCall(std::string const &name,
322 std::vector<SdfPredicateExpression::FnArg> const &args) const {
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(
414 std::is_convertible<DomainType, DomainArgType>::value, "");
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 =
435 TfMetaApply<TfMetaDecay, TfMetaApply<TfMetaTail, FullParams>>;
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 =
566 std::get<std::tuple_size<Tuple>::value-1>(typedArgs);
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<
591 std::tuple_element_t<std::tuple_size<ParamsTuple>::value-1,
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 =
616 TfMetaApply<TfMetaDecay, TfMetaApply<TfMetaTail, FullParams>>;
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
769PXR_NAMESPACE_CLOSE_SCOPE
770
771#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...
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'.
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:164
T UncheckedRemove()
Make this value empty and return the held T instance.
Definition: value.h:1041
bool IsEmpty() const
Returns true iff this value is empty.
Definition: value.h:1300
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:100
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition: diagnostic.h:85
#define TF_UNUSED(x)
Stops compiler from producing unused argument or variable warnings.
Definition: tf.h:185
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>.