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());
280 if (
this != &other) {
282 *
this = std::move(copy);
292 return Define(name, std::forward<Fn>(fn), {});
308 if (
auto obinder = _OverloadBinder<std::decay_t<Fn>>
309 ::TryCreate(std::forward<Fn>(fn), namesAndDefaults)) {
310 _binders[name].push_back(std::move(obinder));
324 auto binder = _CustomBinder<
325 std::decay_t<Fn>>::Create(std::forward<Fn>(fn));
326 _binders[name].push_back(std::move(binder));
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()) {
343 for (
auto i = iter->second.rbegin(),
344 end = iter->second.rend(); i != end; ++i) {
345 ret = (*i)->Bind(args);
353 template <
class ParamType>
354 static void _CheckOneNameAndDefault(
355 bool &valid,
size_t index,
size_t numParams,
356 NamesAndDefaults
const &namesAndDefaults) {
360 std::vector<NamesAndDefaults::Param>
const &
361 params = namesAndDefaults.GetParams();
363 size_t nFromEnd = numParams - index - 1;
364 if (nFromEnd >= params.size()) {
369 size_t namesIndex = params.size() - nFromEnd - 1;
371 auto const ¶m = params[namesIndex];
372 if (!param.val.IsEmpty() && !param.val.CanCast<ParamType>()) {
374 "type '%s' cannot convert to c++ argument of "
375 "type '%s' at index %zu",
377 param.val.GetTypeName().c_str(),
384 template <
class ParamsTuple,
size_t... I>
386 _CheckNamesAndDefaultsImpl(
387 NamesAndDefaults
const &namesAndDefaults,
388 std::index_sequence<I...>) {
392 constexpr size_t N = std::tuple_size<ParamsTuple>::value;
397 (_CheckOneNameAndDefault<std::tuple_element_t<N-I-1, ParamsTuple>>(
398 valid, N-I-1, N, namesAndDefaults), 0)...
406 _CheckNamesAndDefaultsWithSignature(
407 NamesAndDefaults
const &namesAndDefaults) {
409 if (!namesAndDefaults.CheckValidity()) {
413 using Traits = TfFunctionTraits<Fn>;
417 std::is_same<
typename Traits::ReturnType,
420 typename Traits::ReturnType,
bool>::value,
"");
424 using DomainArgType =
typename Traits::template NthArg<0>;
426 std::is_convertible<DomainType, DomainArgType>::value,
"");
431 std::vector<NamesAndDefaults::Param>
const &
432 params = namesAndDefaults.GetParams();
433 if (params.size() > Traits::Arity-1) {
435 "C++ function arguments (%zu)",
436 params.size(), Traits::Arity-1);
443 if (!params.empty()) {
445 using FullParams =
typename Traits::ArgTypes;
447 TfMetaApply<TfMetaDecay, TfMetaApply<TfMetaTail, FullParams>>;
448 using ParamsTuple = TfMetaApply<std::tuple, Params>;
450 return _CheckNamesAndDefaultsImpl<ParamsTuple>(
451 namesAndDefaults, std::make_index_sequence<Traits::Arity-1> {});
456 template <
class ParamType>
457 static void _TryBindOne(
458 size_t index,
size_t numParams,
460 bool &boundAllParams,
461 std::vector<SdfPredicateExpression::FnArg>
const &args,
462 std::vector<bool> &boundArgs,
463 NamesAndDefaults
const &namesAndDefaults) {
474 if (!boundAllParams) {
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 = ¶ms[index - numUnnamed];
492 (index < args.size() && args[index].argName.empty()) ?
493 &args[index] :
nullptr;
495 auto tryBind = [&](
VtValue const &val,
size_t argIndex) {
499 boundArgs[argIndex] =
true;
502 boundAllParams =
false;
506 if (!paramNameAndDefault) {
508 if (!posArg || !posArg->argName.empty()) {
509 boundAllParams =
false;
513 tryBind(posArg->value, index);
518 tryBind(posArg->value, index);
524 for (
size_t i = 0, end = args.size(); i != end; ++i) {
529 if (args[i].argName == paramNameAndDefault->name) {
531 tryBind(args[i].value, i);
543 boundAllParams =
false;
547 template <
class ParamsTuple,
size_t... I>
549 _TryBindArgs(ParamsTuple ¶ms,
550 std::vector<SdfPredicateExpression::FnArg>
const &args,
551 NamesAndDefaults
const &namesAndDefaults,
552 std::index_sequence<I...>,
553 std::vector<bool> &boundArgs) {
558 boundArgs.assign(args.size(),
false);
563 (_TryBindOne(I, std::tuple_size<ParamsTuple>::value,
564 std::get<I>(params), bound,
565 args, boundArgs, namesAndDefaults), 0)...
571 template <
class Tuple>
573 _FillArbitraryArgs(std::true_type,
574 std::vector<SdfPredicateExpression::FnArg>
const &args,
575 std::vector<bool>
const &boundArgs,
577 std::vector<SdfPredicateExpression::FnArg> &rest =
578 std::get<std::tuple_size<Tuple>::value-1>(typedArgs);
583 for (
size_t i = 0; i != args.size(); ++i) {
585 rest.push_back(args[i]);
592 _FillArbitraryArgs(std::false_type,
593 std::vector<SdfPredicateExpression::FnArg>
const &,
594 std::vector<bool>
const &,
599 template <
class ParamsTuple>
600 static constexpr bool
601 _TakesArbitraryArgs(std::true_type) {
603 std::tuple_element_t<std::tuple_size<ParamsTuple>::value-1,
605 std::vector<SdfPredicateExpression::FnArg>
609 template <
class ParamsTuple>
610 static constexpr bool
611 _TakesArbitraryArgs(std::false_type) {
617 _TryToBindCall(Fn
const &fn,
618 std::vector<SdfPredicateExpression::FnArg>
const &args,
619 NamesAndDefaults
const &namesAndDefaults) {
625 using Traits = TfFunctionTraits<Fn>;
626 using FullParams =
typename Traits::ArgTypes;
628 TfMetaApply<TfMetaDecay, TfMetaApply<TfMetaTail, FullParams>>;
629 using ParamsTuple = TfMetaApply<std::tuple, Params>;
635 static const bool TakesArbitraryArgs =
636 _TakesArbitraryArgs<ParamsTuple>(
637 std::integral_constant<bool, Traits::Arity >= 2> {});
639 size_t minArgs = Traits::Arity-1 - namesAndDefaults.GetNumDefaults();
640 size_t maxArgs = TakesArbitraryArgs ? size_t(-1) : Traits::Arity-1;
644 static const size_t NumBindableArgs =
645 Traits::Arity - (TakesArbitraryArgs ? 2 : 1);
647 if (args.size() < minArgs) {
649 "%zu given", minArgs, minArgs == 1 ?
"" :
"s",
653 if (args.size() > maxArgs) {
655 maxArgs, maxArgs == 1 ?
"" :
"s", args.size());
659 ParamsTuple typedArgs;
660 std::vector<bool> boundArgs;
661 if (_TryBindArgs(typedArgs, args, namesAndDefaults,
662 std::make_index_sequence<NumBindableArgs> {},
665 std::integral_constant<bool, TakesArbitraryArgs> {},
666 args, boundArgs, typedArgs);
667 return [typedArgs, fn](DomainType
const &obj) {
670 std::tuple_cat(std::make_tuple(obj), typedArgs))
677 struct _OverloadBinderBase
679 virtual ~_OverloadBinderBase() =
default;
681 Bind(std::vector<SdfPredicateExpression::FnArg>
const &args)
const {
684 virtual std::unique_ptr<_OverloadBinderBase> Clone()
const = 0;
686 _OverloadBinderBase() =
default;
688 explicit _OverloadBinderBase(NamesAndDefaults
const &namesAndDefaults)
689 : _namesAndDefaults(namesAndDefaults) {}
695 NamesAndDefaults _namesAndDefaults;
699 struct _OverloadBinder : _OverloadBinderBase
701 ~_OverloadBinder()
override =
default;
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)) {
713 std::unique_ptr<_OverloadBinderBase> Clone()
const override {
714 return std::unique_ptr<
715 _OverloadBinder>(
new _OverloadBinder(*
this));
719 _OverloadBinder(_OverloadBinder
const &) =
default;
721 explicit _OverloadBinder(Fn &&fn,
722 NamesAndDefaults
const &namesAndDefaults)
723 : _OverloadBinderBase(namesAndDefaults)
724 , _fn(
std::move(fn)) {}
726 explicit _OverloadBinder(Fn
const &fn,
727 NamesAndDefaults
const &namesAndDefaults)
728 : _OverloadBinder(Fn(fn), namesAndDefaults) {}
735 return _TryToBindCall(_fn, args, this->_namesAndDefaults);
742 struct _CustomBinder : _OverloadBinderBase
744 ~_CustomBinder()
override =
default;
746 static std::unique_ptr<_CustomBinder>
748 return std::unique_ptr<_CustomBinder>(
749 new _CustomBinder(std::move(fn)));
752 std::unique_ptr<_OverloadBinderBase> Clone()
const override {
753 return std::unique_ptr<_CustomBinder>(
new _CustomBinder(*
this));
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)) {}
773 using _OverloadBinderBasePtr = std::unique_ptr<_OverloadBinderBase>;
776 std::string, std::vector<_OverloadBinderBasePtr>