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());
281 if (
this != &other) {
283 *
this = std::move(copy);
293 return Define(name, std::forward<Fn>(fn), {});
309 if (
auto obinder = _OverloadBinder<std::decay_t<Fn>>
310 ::TryCreate(std::forward<Fn>(fn), namesAndDefaults)) {
311 _binders[name].push_back(std::move(obinder));
325 auto binder = _CustomBinder<
326 std::decay_t<Fn>>::Create(std::forward<Fn>(fn));
327 _binders[name].push_back(std::move(binder));
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()) {
344 for (
auto i = iter->second.rbegin(),
345 end = iter->second.rend(); i != end; ++i) {
346 ret = (*i)->Bind(args);
354 template <
class ParamType>
355 static void _CheckOneNameAndDefault(
356 bool &valid,
size_t index,
size_t numParams,
357 NamesAndDefaults
const &namesAndDefaults) {
361 std::vector<NamesAndDefaults::Param>
const &
362 params = namesAndDefaults.GetParams();
364 size_t nFromEnd = numParams - index - 1;
365 if (nFromEnd >= params.size()) {
370 size_t namesIndex = params.size() - nFromEnd - 1;
372 auto const ¶m = params[namesIndex];
373 if (!param.val.IsEmpty() && !param.val.CanCast<ParamType>()) {
375 "type '%s' cannot convert to c++ argument of "
376 "type '%s' at index %zu",
378 param.val.GetTypeName().c_str(),
385 template <
class ParamsTuple,
size_t... I>
387 _CheckNamesAndDefaultsImpl(
388 NamesAndDefaults
const &namesAndDefaults,
389 std::index_sequence<I...>) {
393 constexpr size_t N = std::tuple_size<ParamsTuple>::value;
398 (_CheckOneNameAndDefault<std::tuple_element_t<N-I-1, ParamsTuple>>(
399 valid, N-I-1, N, namesAndDefaults), 0)...
407 _CheckNamesAndDefaultsWithSignature(
408 NamesAndDefaults
const &namesAndDefaults) {
410 if (!namesAndDefaults.CheckValidity()) {
414 using Traits = TfFunctionTraits<Fn>;
418 std::is_same<
typename Traits::ReturnType,
421 typename Traits::ReturnType,
bool>::value,
"");
425 using DomainArgType =
typename Traits::template NthArg<0>;
427 std::is_convertible<DomainType, DomainArgType>::value,
"");
432 std::vector<NamesAndDefaults::Param>
const &
433 params = namesAndDefaults.GetParams();
434 if (params.size() > Traits::Arity-1) {
436 "C++ function arguments (%zu)",
437 params.size(), Traits::Arity-1);
444 if (!params.empty()) {
446 using FullParams =
typename Traits::ArgTypes;
448 TfMetaApply<TfMetaDecay, TfMetaApply<TfMetaTail, FullParams>>;
449 using ParamsTuple = TfMetaApply<std::tuple, Params>;
451 return _CheckNamesAndDefaultsImpl<ParamsTuple>(
452 namesAndDefaults, std::make_index_sequence<Traits::Arity-1> {});
457 template <
class ParamType>
458 static void _TryBindOne(
459 size_t index,
size_t numParams,
461 bool &boundAllParams,
462 std::vector<SdfPredicateExpression::FnArg>
const &args,
463 std::vector<bool> &boundArgs,
464 NamesAndDefaults
const &namesAndDefaults) {
475 if (!boundAllParams) {
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 = ¶ms[index - numUnnamed];
493 (index < args.size() && args[index].argName.empty()) ?
494 &args[index] :
nullptr;
496 auto tryBind = [&](
VtValue const &val,
size_t argIndex) {
500 boundArgs[argIndex] =
true;
503 boundAllParams =
false;
507 if (!paramNameAndDefault) {
509 if (!posArg || !posArg->argName.empty()) {
510 boundAllParams =
false;
514 tryBind(posArg->value, index);
519 tryBind(posArg->value, index);
525 for (
size_t i = 0, end = args.size(); i != end; ++i) {
530 if (args[i].argName == paramNameAndDefault->name) {
532 tryBind(args[i].value, i);
544 boundAllParams =
false;
548 template <
class ParamsTuple,
size_t... I>
550 _TryBindArgs(ParamsTuple ¶ms,
551 std::vector<SdfPredicateExpression::FnArg>
const &args,
552 NamesAndDefaults
const &namesAndDefaults,
553 std::index_sequence<I...>,
554 std::vector<bool> &boundArgs) {
562 ARCH_PRAGMA_ARRAY_BOUNDS
563 ARCH_PRAGMA_STRINGOP_OVERFLOW
564 boundArgs.assign(args.size(),
false);
570 (_TryBindOne(I, std::tuple_size<ParamsTuple>::value,
571 std::get<I>(params), bound,
572 args, boundArgs, namesAndDefaults), 0)...
578 template <
class Tuple>
580 _FillArbitraryArgs(std::true_type,
581 std::vector<SdfPredicateExpression::FnArg>
const &args,
582 std::vector<bool>
const &boundArgs,
584 std::vector<SdfPredicateExpression::FnArg> &rest =
585 std::get<std::tuple_size<Tuple>::value-1>(typedArgs);
590 for (
size_t i = 0; i != args.size(); ++i) {
592 rest.push_back(args[i]);
599 _FillArbitraryArgs(std::false_type,
600 std::vector<SdfPredicateExpression::FnArg>
const &,
601 std::vector<bool>
const &,
606 template <
class ParamsTuple>
607 static constexpr bool
608 _TakesArbitraryArgs(std::true_type) {
610 std::tuple_element_t<std::tuple_size<ParamsTuple>::value-1,
612 std::vector<SdfPredicateExpression::FnArg>
616 template <
class ParamsTuple>
617 static constexpr bool
618 _TakesArbitraryArgs(std::false_type) {
624 _TryToBindCall(Fn
const &fn,
625 std::vector<SdfPredicateExpression::FnArg>
const &args,
626 NamesAndDefaults
const &namesAndDefaults) {
632 using Traits = TfFunctionTraits<Fn>;
633 using FullParams =
typename Traits::ArgTypes;
635 TfMetaApply<TfMetaDecay, TfMetaApply<TfMetaTail, FullParams>>;
636 using ParamsTuple = TfMetaApply<std::tuple, Params>;
642 static const bool TakesArbitraryArgs =
643 _TakesArbitraryArgs<ParamsTuple>(
644 std::integral_constant<bool, Traits::Arity >= 2> {});
646 size_t minArgs = Traits::Arity-1 - namesAndDefaults.GetNumDefaults();
647 size_t maxArgs = TakesArbitraryArgs ? size_t(-1) : Traits::Arity-1;
651 static const size_t NumBindableArgs =
652 Traits::Arity - (TakesArbitraryArgs ? 2 : 1);
654 if (args.size() < minArgs) {
656 "%zu given", minArgs, minArgs == 1 ?
"" :
"s",
660 if (args.size() > maxArgs) {
662 maxArgs, maxArgs == 1 ?
"" :
"s", args.size());
666 ParamsTuple typedArgs;
667 std::vector<bool> boundArgs;
668 if (_TryBindArgs(typedArgs, args, namesAndDefaults,
669 std::make_index_sequence<NumBindableArgs> {},
672 std::integral_constant<bool, TakesArbitraryArgs> {},
673 args, boundArgs, typedArgs);
674 return [typedArgs, fn](DomainType
const &obj) {
677 std::tuple_cat(std::make_tuple(obj), typedArgs))
684 struct _OverloadBinderBase
686 virtual ~_OverloadBinderBase() =
default;
688 Bind(std::vector<SdfPredicateExpression::FnArg>
const &args)
const {
691 virtual std::unique_ptr<_OverloadBinderBase> Clone()
const = 0;
693 _OverloadBinderBase() =
default;
695 explicit _OverloadBinderBase(NamesAndDefaults
const &namesAndDefaults)
696 : _namesAndDefaults(namesAndDefaults) {}
702 NamesAndDefaults _namesAndDefaults;
706 struct _OverloadBinder : _OverloadBinderBase
708 ~_OverloadBinder()
override =
default;
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)) {
720 std::unique_ptr<_OverloadBinderBase> Clone()
const override {
721 return std::unique_ptr<
722 _OverloadBinder>(
new _OverloadBinder(*
this));
726 _OverloadBinder(_OverloadBinder
const &) =
default;
728 explicit _OverloadBinder(Fn &&fn,
729 NamesAndDefaults
const &namesAndDefaults)
730 : _OverloadBinderBase(namesAndDefaults)
731 , _fn(
std::move(fn)) {}
733 explicit _OverloadBinder(Fn
const &fn,
734 NamesAndDefaults
const &namesAndDefaults)
735 : _OverloadBinder(Fn(fn), namesAndDefaults) {}
742 return _TryToBindCall(_fn, args, this->_namesAndDefaults);
749 struct _CustomBinder : _OverloadBinderBase
751 ~_CustomBinder()
override =
default;
753 static std::unique_ptr<_CustomBinder>
755 return std::unique_ptr<_CustomBinder>(
756 new _CustomBinder(std::move(fn)));
759 std::unique_ptr<_OverloadBinderBase> Clone()
const override {
760 return std::unique_ptr<_CustomBinder>(
new _CustomBinder(*
this));
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)) {}
780 using _OverloadBinderBasePtr = std::unique_ptr<_OverloadBinderBase>;
783 std::string, std::vector<_OverloadBinderBasePtr>