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 { 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
126 bool GetValue() const {
127 return _value;
128 }
129
131 Constancy GetConstancy() const {
132 return _constancy;
133 }
134
136 bool IsConstant() const {
137 return GetConstancy() == ConstantOverDescendants;
138 }
139
140#if !defined(doxygen)
141 using UnspecifiedBoolType = bool (SdfPredicateFunctionResult::*);
142#endif
143
145 operator UnspecifiedBoolType() const {
146 return _value ? &SdfPredicateFunctionResult::_value : nullptr;
147 }
148
151 return { !_value, _constancy };
152 }
153
159 _value = other._value;
160 if (_constancy == ConstantOverDescendants &&
161 other._constancy == MayVaryOverDescendants) {
162 _constancy = MayVaryOverDescendants;
163 }
164 }
165
166private:
167 friend bool operator==(SdfPredicateFunctionResult lhs,
169 return lhs._value == rhs._value &&
170 lhs._constancy == rhs._constancy;
171 }
172 friend bool operator!=(SdfPredicateFunctionResult lhs,
174 return !(lhs == rhs);
175 }
176
177 friend bool operator==(SdfPredicateFunctionResult pfr, bool rhs) {
178 return pfr._value == rhs;
179 }
180 friend bool operator==(bool lhs, SdfPredicateFunctionResult pfr) {
181 return lhs == pfr._value;
182 }
183 friend bool operator!=(SdfPredicateFunctionResult pfr, bool rhs) {
184 return pfr._value != rhs;
185 }
186 friend bool operator!=(bool lhs, SdfPredicateFunctionResult pfr) {
187 return lhs != pfr._value;
188 }
189
190 bool _value;
191 Constancy _constancy;
192};
193
194// fwd decl
195template <class DomainType>
197
198// fwd decl
199template <class DomainType>
201
202// fwd decl
203template <class DomainType>
207
213template <class DomainType>
215{
217 SdfLinkPredicateExpression<DomainType>(
218 SdfPredicateExpression const &expr,
219 SdfPredicateLibrary const &lib);
220
222
223public:
226 std::function<SdfPredicateFunctionResult (DomainType const &)>;
227
230
233
236 for (auto iter = other._binders.begin(), end = other._binders.end();
237 iter != end; ++iter) {
238 auto &theseBinders = _binders[iter->first];
239 for (auto const &otherBinder: iter->second) {
240 theseBinders.push_back(otherBinder->Clone());
241 }
242 }
243 }
244
247
250 if (this != &other) {
251 SdfPredicateLibrary copy(other);
252 *this = std::move(copy);
253 }
254 return *this;
255 }
256
260 template <class Fn>
261 SdfPredicateLibrary &Define(char const *name, Fn &&fn) {
262 return Define(name, std::forward<Fn>(fn), {});
263 }
264
269 template <class Fn>
271 Define(std::string const &name, Fn &&fn,
272 NamesAndDefaults const &namesAndDefaults) {
273 // Try to create a new overload binder for 'name'. The main operation a
274 // binder does is, when "linking" a predicate expression, given a
275 // specific set of arguments from the expression, check to see if those
276 // arguments can be bound to 'fn', and if so return a type-erased
277 // callable that invokes fn with those arguments.
278 if (auto obinder = _OverloadBinder<std::decay_t<Fn>>
279 ::TryCreate(std::forward<Fn>(fn), namesAndDefaults)) {
280 _binders[name].push_back(std::move(obinder));
281 }
282 return *this;
283 }
284
291 template <class Fn>
293 DefineBinder(std::string const &name, Fn &&fn) {
294 auto binder = _CustomBinder<
295 std::decay_t<Fn>>::Create(std::forward<Fn>(fn));
296 _binders[name].push_back(std::move(binder));
297 return *this;
298 }
299
300private:
301
303 _BindCall(std::string const &name,
304 std::vector<SdfPredicateExpression::FnArg> const &args) const {
306 auto iter = _binders.find(name);
307 if (iter == _binders.end()) {
308 TF_RUNTIME_ERROR("No registered function '%s'", name.c_str());
309 return ret;
310 }
311 // Run thru optimistically first -- if we fail to bind to any overload,
312 // then produce an error message with all the overload signatures.
313 for (auto i = iter->second.rbegin(),
314 end = iter->second.rend(); i != end; ++i) {
315 ret = (*i)->Bind(args);
316 if (ret) {
317 break;
318 }
319 }
320 return ret;
321 }
322
323 template <class ParamType>
324 static void _CheckOneNameAndDefault(
325 bool &valid, size_t index, size_t numParams,
326 NamesAndDefaults const &namesAndDefaults) {
327
328 // If the namesIndex-th param has a default, it must be convertible to
329 // the ArgIndex-th type.
330 std::vector<NamesAndDefaults::Param> const &
331 params = namesAndDefaults.GetParams();
332
333 size_t nFromEnd = numParams - index - 1;
334 if (nFromEnd >= params.size()) {
335 // No more names & defaults to check.
336 return;
337 }
338
339 size_t namesIndex = params.size() - nFromEnd - 1;
340
341 auto const &param = params[namesIndex];
342 if (!param.val.IsEmpty() && !param.val.CanCast<ParamType>()) {
343 TF_CODING_ERROR("Predicate default parameter '%s' value of "
344 "type '%s' cannot convert to c++ argument of "
345 "type '%s' at index %zu",
346 param.name.c_str(),
347 param.val.GetTypeName().c_str(),
348 ArchGetDemangled<ParamType>().c_str(),
349 index);
350 valid = false;
351 }
352 }
353
354 template <class ParamsTuple, size_t... I>
355 static bool
356 _CheckNamesAndDefaultsImpl(
357 NamesAndDefaults const &namesAndDefaults,
358 std::index_sequence<I...>) {
359 // A fold expression would let us just do &&, but that's c++'17, so we
360 // just do all of them and set a bool.
361 bool valid = true;
362 constexpr size_t N = std::tuple_size<ParamsTuple>::value;
363 // Need an unused array so we can use an initializer list to invoke
364 // _CheckOneNameAndDefault N times.
365 int unused[] = {
366 0,
367 (_CheckOneNameAndDefault<std::tuple_element_t<N-I-1, ParamsTuple>>(
368 valid, N-I-1, N, namesAndDefaults), 0)...
369 };
370 TF_UNUSED(unused);
371 return valid;
372 }
373
374 template <class Fn>
375 static bool
376 _CheckNamesAndDefaultsWithSignature(
377 NamesAndDefaults const &namesAndDefaults) {
378 // Basic check for declared names & defaults.
379 if (!namesAndDefaults.CheckValidity()) {
380 return false;
381 }
382
383 using Traits = TfFunctionTraits<Fn>;
384
385 // Return type must convert to bool.
386 static_assert(
387 std::is_same<typename Traits::ReturnType,
389 std::is_convertible<
390 typename Traits::ReturnType, bool>::value, "");
391
392 // Fn must have at least one argument, and DomainType must be
393 // convertible to the first arg.
394 using DomainArgType = typename Traits::template NthArg<0>;
395 static_assert(
396 std::is_convertible<DomainType, DomainArgType>::value, "");
397
398 // Issue an error if there are more named arguments than c++ function
399 // arguments. Subtract one from Arity to account for the leading
400 // DomainType argument.
401 std::vector<NamesAndDefaults::Param> const &
402 params = namesAndDefaults.GetParams();
403 if (params.size() > Traits::Arity-1) {
404 TF_CODING_ERROR("Predicate named arguments (%zu) exceed number of "
405 "C++ function arguments (%zu)",
406 params.size(), Traits::Arity-1);
407 return false;
408 }
409
410 // Now check the names and defaults against the Fn signature, from back
411 // to front, since namesAndDefaults must be "right-aligned" -- that is,
412 // any unnamed arguments must come first.
413 if (!params.empty()) {
414 // Strip DomainType arg...
415 using FullParams = typename Traits::ArgTypes;
416 using Params =
417 TfMetaApply<TfMetaDecay, TfMetaApply<TfMetaTail, FullParams>>;
418 using ParamsTuple = TfMetaApply<std::tuple, Params>;
419
420 return _CheckNamesAndDefaultsImpl<ParamsTuple>(
421 namesAndDefaults, std::make_index_sequence<Traits::Arity-1> {});
422 }
423 return true;
424 }
425
426 template <class ParamType>
427 static void _TryBindOne(
428 size_t index, size_t numParams,
429 ParamType &param,
430 bool &boundAllParams,
431 std::vector<SdfPredicateExpression::FnArg> const &args,
432 std::vector<bool> &boundArgs,
433 NamesAndDefaults const &namesAndDefaults) {
434
435 // Bind the index-th 'param' from 'args' &
436 // 'namesAndDefaults'. 'boundArgs' corresponds to 'args' and indicates
437 // which have already been bound. This function sets one bit in
438 // 'boundArgs' if it binds one of them to a parameter. It may bind a
439 // default from 'namesAndDefaults', in which case it sets no bit. If no
440 // suitable binding can be determined for this parameter, set
441 // 'boundAllParams' false.
442
443 // If we've already failed to bind, just return early.
444 if (!boundAllParams) {
445 return;
446 }
447
448 // namesAndDefaults covers trailing parameters -- that is, there may be
449 // zero or more leading unnamed parameters.
450 std::vector<NamesAndDefaults::Param> const &
451 params = namesAndDefaults.GetParams();
452 size_t numUnnamed = params.size() - numParams;
453 NamesAndDefaults::Param const *paramNameAndDefault = nullptr;
454 if (index >= numUnnamed) {
455 paramNameAndDefault = &params[index - numUnnamed];
456 }
457
458 // If this is a purely positional parameter (paramNameAndDefault is
459 // nullptr) or the caller supplied a positional arg (unnamed) then we
460 // use index-correspondence.
461 auto const *posArg =
462 (index < args.size() && args[index].argName.empty()) ?
463 &args[index] : nullptr;
464
465 auto tryBind = [&](VtValue const &val, size_t argIndex) {
466 VtValue cast = VtValue::Cast<ParamType>(val);
467 if (!cast.IsEmpty()) {
468 param = cast.UncheckedRemove<ParamType>();
469 boundArgs[argIndex] = true;
470 return true;
471 }
472 boundAllParams = false;
473 return false;
474 };
475
476 if (!paramNameAndDefault) {
477 // If this is a positional parameter, the arg must be too.
478 if (!posArg || !posArg->argName.empty()) {
479 boundAllParams = false;
480 return;
481 }
482 // Try to bind posArg.
483 tryBind(posArg->value, index);
484 return;
485 }
486 else if (posArg) {
487 // Passed a positional arg, try to bind.
488 tryBind(posArg->value, index);
489 return;
490 }
491
492 // Only possibility is a keyword arg. If there's a matching name, try
493 // to bind that, otherwise try to fill a default.
494 for (size_t i = 0, end = args.size(); i != end; ++i) {
495 if (boundArgs[i]) {
496 // Already bound.
497 continue;
498 }
499 if (args[i].argName == paramNameAndDefault->name) {
500 // Matching name -- try to bind.
501 tryBind(args[i].value, i);
502 return;
503 }
504 }
505
506 // No matching arg, try to fill default val.
507 VtValue cast = VtValue::Cast<ParamType>(paramNameAndDefault->val);
508 if (!cast.IsEmpty()) {
509 param = cast.UncheckedRemove<ParamType>();
510 }
511 else {
512 // Error, could not fill default.
513 boundAllParams = false;
514 }
515 }
516
517 template <class ParamsTuple, size_t... I>
518 static bool
519 _TryBindArgs(ParamsTuple &params,
520 std::vector<SdfPredicateExpression::FnArg> const &args,
521 NamesAndDefaults const &namesAndDefaults,
522 std::index_sequence<I...>,
523 std::vector<bool> &boundArgs) {
524
525 // A fold expression would let us just do &&, but that's '17, so we just
526 // do all of them and set a bool.
527 bool bound = true;
528 boundArgs.assign(args.size(), false);
529 // Need a unused array so we can use an initializer list to invoke
530 // _TryBindOne N times.
531 int unused[] = {
532 0,
533 (_TryBindOne(I, std::tuple_size<ParamsTuple>::value,
534 std::get<I>(params), bound,
535 args, boundArgs, namesAndDefaults), 0)...
536 };
537 TF_UNUSED(unused);
538 return bound;
539 }
540
541 template <class Tuple>
542 static void
543 _FillArbitraryArgs(std::true_type,
544 std::vector<SdfPredicateExpression::FnArg> const &args,
545 std::vector<bool> const &boundArgs,
546 Tuple &typedArgs) {
547 std::vector<SdfPredicateExpression::FnArg> &rest =
548 std::get<std::tuple_size<Tuple>::value-1>(typedArgs);
549 // 'boundArgs' and 'args' correspond. Fill 'rest' with the elements of
550 // 'args' for which the corresponding element of 'boundArgs' is false,
551 // in order.
552 rest.clear();
553 for (size_t i = 0; i != args.size(); ++i) {
554 if (!boundArgs[i]) {
555 rest.push_back(args[i]);
556 }
557 }
558 }
559
560 template <class T>
561 static void
562 _FillArbitraryArgs(std::false_type,
563 std::vector<SdfPredicateExpression::FnArg> const &,
564 std::vector<bool> const &,
565 T const &) {
566 // Do nothing.
567 }
568
569 template <class ParamsTuple>
570 static constexpr bool
571 _TakesArbitraryArgs(std::true_type) { // arity >= 2.
572 return std::is_same<
573 std::tuple_element_t<std::tuple_size<ParamsTuple>::value-1,
574 ParamsTuple>,
575 std::vector<SdfPredicateExpression::FnArg>
576 >::value;
577 }
578
579 template <class ParamsTuple>
580 static constexpr bool
581 _TakesArbitraryArgs(std::false_type) { // arity < 2.
582 return false;
583 }
584
585 template <class Fn>
586 static PredicateFunction
587 _TryToBindCall(Fn const &fn,
588 std::vector<SdfPredicateExpression::FnArg> const &args,
589 NamesAndDefaults const &namesAndDefaults) {
590
591 // We need to determine an argument for each parameter of Fn, then make
592 // a callable object that calls that function.
593
594 // Strip DomainType arg...
595 using Traits = TfFunctionTraits<Fn>;
596 using FullParams = typename Traits::ArgTypes;
597 using Params =
598 TfMetaApply<TfMetaDecay, TfMetaApply<TfMetaTail, FullParams>>;
599 using ParamsTuple = TfMetaApply<std::tuple, Params>;
600
601 // If there are at least two parameters to Fn (first has to be
602 // DomainType) and the last parameter type is vector<FnArg>, then
603 // namesAndDefaults does not apply to it, and any remaining unbound args
604 // after binding are passed through that parameter.
605 static const bool TakesArbitraryArgs =
606 _TakesArbitraryArgs<ParamsTuple>(
607 std::integral_constant<bool, Traits::Arity >= 2> {});
608
609 size_t minArgs = Traits::Arity-1 - namesAndDefaults.GetNumDefaults();
610 size_t maxArgs = TakesArbitraryArgs ? size_t(-1) : Traits::Arity-1;
611
612 // Number of bindable args is arity-1 (for the domain arg) or -2 if the
613 // trailing parameter is the vector<FnArg> bag of extra arguments.
614 static const size_t NumBindableArgs =
615 Traits::Arity - (TakesArbitraryArgs ? 2 : 1);
616
617 if (args.size() < minArgs) {
618 TF_RUNTIME_ERROR("Function requires at least %zu argument%s, "
619 "%zu given", minArgs, minArgs == 1 ? "" : "s",
620 args.size());
621 return {};
622 }
623 if (args.size() > maxArgs) {
624 TF_RUNTIME_ERROR("Function takes at most %zu argument%s, %zu given",
625 maxArgs, maxArgs == 1 ? "" : "s", args.size());
626 return {};
627 }
628
629 ParamsTuple typedArgs;
630 std::vector<bool> boundArgs;
631 if (_TryBindArgs(typedArgs, args, namesAndDefaults,
632 std::make_index_sequence<NumBindableArgs> {},
633 boundArgs)) {
634 _FillArbitraryArgs(
635 std::integral_constant<bool, TakesArbitraryArgs> {},
636 args, boundArgs, typedArgs);
637 return [typedArgs, fn](DomainType const &obj) {
639 std::apply(fn,
640 std::tuple_cat(std::make_tuple(obj), typedArgs))
641 };
642 };
643 }
644 return {};
645 }
646
647 struct _OverloadBinderBase
648 {
649 virtual ~_OverloadBinderBase() = default;
651 Bind(std::vector<SdfPredicateExpression::FnArg> const &args) const {
652 return _Bind(args);
653 }
654 virtual std::unique_ptr<_OverloadBinderBase> Clone() const = 0;
655 protected:
656 _OverloadBinderBase() = default;
657
658 explicit _OverloadBinderBase(NamesAndDefaults const &namesAndDefaults)
659 : _namesAndDefaults(namesAndDefaults) {}
660
661 virtual PredicateFunction
662 _Bind(std::vector<
663 SdfPredicateExpression::FnArg> const &args) const = 0;
664
665 NamesAndDefaults _namesAndDefaults;
666 };
667
668 template <class Fn>
669 struct _OverloadBinder : _OverloadBinderBase
670 {
671 ~_OverloadBinder() override = default;
672
673 static std::unique_ptr<_OverloadBinder>
674 TryCreate(Fn &&fn, NamesAndDefaults const &nd) {
675 auto ret = std::unique_ptr<_OverloadBinder>(
676 new _OverloadBinder(std::move(fn), nd));
677 if (!_CheckNamesAndDefaultsWithSignature<Fn>(nd)) {
678 ret.reset();
679 }
680 return ret;
681 }
682
683 std::unique_ptr<_OverloadBinderBase> Clone() const override {
684 return std::unique_ptr<
685 _OverloadBinder>(new _OverloadBinder(*this));
686 }
687
688 private:
689 _OverloadBinder(_OverloadBinder const &) = default;
690
691 explicit _OverloadBinder(Fn &&fn,
692 NamesAndDefaults const &namesAndDefaults)
693 : _OverloadBinderBase(namesAndDefaults)
694 , _fn(std::move(fn)) {}
695
696 explicit _OverloadBinder(Fn const &fn,
697 NamesAndDefaults const &namesAndDefaults)
698 : _OverloadBinder(Fn(fn), namesAndDefaults) {}
699
701 _Bind(std::vector<
702 SdfPredicateExpression::FnArg> const &args) const override {
703 // Try to bind 'args' to _fn's parameters, taking _namesAndDefaults
704 // into account.
705 return _TryToBindCall(_fn, args, this->_namesAndDefaults);
706 }
707
708 Fn _fn;
709 };
710
711 template <class Fn>
712 struct _CustomBinder : _OverloadBinderBase
713 {
714 ~_CustomBinder() override = default;
715
716 static std::unique_ptr<_CustomBinder>
717 Create(Fn &&fn) {
718 return std::unique_ptr<_CustomBinder>(
719 new _CustomBinder(std::move(fn)));
720 }
721
722 std::unique_ptr<_OverloadBinderBase> Clone() const override {
723 return std::unique_ptr<_CustomBinder>(new _CustomBinder(*this));
724 }
725
726 private:
727 _CustomBinder(_CustomBinder const &) = default;
728 explicit _CustomBinder(Fn &&fn)
729 : _OverloadBinderBase()
730 , _fn(std::move(fn)) {}
731 explicit _CustomBinder(Fn const &fn) : _CustomBinder(Fn(fn)) {}
732
734 _Bind(std::vector<
735 SdfPredicateExpression::FnArg> const &args) const override {
736 // Call _fn to try to bind 'args', producing a callable.
737 return _fn(args);
738 }
739
740 Fn _fn;
741 };
742
743 using _OverloadBinderBasePtr = std::unique_ptr<_OverloadBinderBase>;
744
746 std::string, std::vector<_OverloadBinderBasePtr>
747 > _binders;
748};
749
750PXR_NAMESPACE_CLOSE_SCOPE
751
752#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:152
T UncheckedRemove()
Make this value empty and return the held T instance.
Definition: value.h:1008
bool IsEmpty() const
Returns true iff this value is empty.
Definition: value.h:1275
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>.