@@ -462,6 +462,10 @@ bool Cppyy::IsClassType(TCppType_t type) {
462462// returns true if no new type was added.
463463bool Cppyy::AppendTypesSlow (const std::string &name,
464464 std::vector<Cpp::TemplateArgInfo>& types) {
465+
466+ // Add no new type if string is empty
467+ if (name.empty ()) return true ;
468+
465469 // Try going via Cppyy::GetType first.
466470 if (Cppyy::TCppType_t type = GetType (name, /* enable_slow_lookup=*/ true )) {
467471 types.push_back (type);
@@ -1308,9 +1312,9 @@ ptrdiff_t Cppyy::GetBaseOffset(TCppScope_t derived, TCppScope_t base,
13081312// return (TCppIndex_t)0; // unknown class?
13091313// }
13101314
1311- std::vector<Cppyy::TCppMethod_t> Cppyy::GetClassMethods (TCppScope_t scope )
1315+ void Cppyy::GetClassMethods (TCppScope_t scope, std::vector<Cppyy::TCppMethod_t> &methods )
13121316{
1313- return Cpp::GetClassMethods (scope);
1317+ Cpp::GetClassMethods (scope, methods );
13141318}
13151319
13161320std::vector<Cppyy::TCppScope_t> Cppyy::GetMethodsFromName (
@@ -1400,7 +1404,8 @@ std::string Cppyy::GetMethodArgDefault(TCppMethod_t method, TCppIndex_t iarg)
14001404
14011405std::string Cppyy::GetMethodSignature (TCppMethod_t method, bool show_formal_args, TCppIndex_t max_args)
14021406{
1403- return Cpp::GetFunctionSignature (method);
1407+ // FIXME : Doesn't work for template functions as it does in cling
1408+ return Cpp::GetFunctionSignature (method);
14041409}
14051410
14061411std::string Cppyy::GetMethodPrototype (TCppMethod_t method, bool show_formal_args)
@@ -1416,40 +1421,23 @@ bool Cppyy::IsConstMethod(TCppMethod_t method)
14161421 return Cpp::IsConstMethod (method);
14171422}
14181423
1419- // Cppyy::TCppIndex_t Cppyy::GetNumTemplatedMethods(TCppScope_t scope, bool accept_namespace)
1420- // {
1421- // if (!accept_namespace && IsNamespace(scope))
1422- // return (TCppIndex_t)0; // enforce lazy
1423- //
1424- // if (scope == GLOBAL_HANDLE) {
1425- // TCollection* coll = gROOT->GetListOfFunctionTemplates();
1426- // if (coll) return (TCppIndex_t)coll->GetSize();
1427- // } else {
1428- // TClassRef& cr = type_from_handle(scope);
1429- // if (cr.GetClass()) {
1430- // TCollection* coll = cr->GetListOfFunctionTemplates(true);
1431- // if (coll) return (TCppIndex_t)coll->GetSize();
1432- // }
1433- // }
1434- //
1435- // // failure ...
1436- // return (TCppIndex_t)0;
1437- // }
1438- //
1439- // std::string Cppyy::GetTemplatedMethodName(TCppScope_t scope, TCppIndex_t imeth)
1440- // {
1441- // if (scope == (TCppScope_t)GLOBAL_HANDLE)
1442- // return ((THashList*)gROOT->GetListOfFunctionTemplates())->At((int)imeth)->GetName();
1443- // else {
1444- // TClassRef& cr = type_from_handle(scope);
1445- // if (cr.GetClass())
1446- // return cr->GetListOfFunctionTemplates(false)->At((int)imeth)->GetName();
1447- // }
1448- //
1449- // // failure ...
1450- // assert(!"should not be called unless GetNumTemplatedMethods() succeeded");
1451- // return "";
1452- // }
1424+ Cppyy::TCppIndex_t Cppyy::GetNumTemplatedMethods (TCppScope_t scope, bool accept_namespace)
1425+ {
1426+ std::vector<Cppyy::TCppMethod_t> mc;
1427+ Cpp::GetFunctionTemplatedDecls (scope, mc);
1428+ return mc.size ();
1429+ }
1430+
1431+ std::string Cppyy::GetTemplatedMethodName (TCppScope_t scope, TCppIndex_t imeth)
1432+ {
1433+ std::vector<Cppyy::TCppMethod_t> mc;
1434+ Cpp::GetFunctionTemplatedDecls (scope, mc);
1435+
1436+ if (imeth < mc.size ()) return GetMethodName (mc[imeth]);
1437+
1438+ return " " ;
1439+ }
1440+
14531441//
14541442// bool Cppyy::IsTemplatedConstructor(TCppScope_t scope, TCppIndex_t imeth)
14551443// {
@@ -1495,85 +1483,40 @@ bool Cppyy::IsTemplatedMethod(TCppMethod_t method)
14951483Cppyy::TCppMethod_t Cppyy::GetMethodTemplate (
14961484 TCppScope_t scope, const std::string& name, const std::string& proto)
14971485{
1498- #ifdef PRINT_DEBUG
1499- printf (" ========== GMT: %s; %s\n " , name.c_str (), proto.c_str ());
1500- #endif
1501- // // There is currently no clean way of extracting a templated method out of ROOT/meta
1502- // // for a variety of reasons, none of them fundamental. The game played below is to
1503- // // first get any pre-existing functions already managed by ROOT/meta, but if that fails,
1504- // // to do an explicit lookup that ignores the prototype (i.e. the full name should be
1505- // // enough), and finally to ignore the template arguments part of the name as this fails
1506- // // in cling if there are default parameters.
1507- // TFunction* func = nullptr; ClassInfo_t* cl = nullptr;
1508- // if (scope == (cppyy_scope_t)GLOBAL_HANDLE) {
1509- // func = gROOT->GetGlobalFunctionWithPrototype(name.c_str(), proto.c_str());
1510- // if (func && name.back() == '>') {
1511- // // make sure that all template parameters match (more are okay, e.g. defaults or
1512- // // ones derived from the arguments or variadic templates)
1513- // if (!template_compare(name, func->GetName()))
1514- // func = nullptr; // happens if implicit conversion matches the overload
1515- // }
1516- // } else {
1517- // TClassRef& cr = type_from_handle(scope);
1518- // if (cr.GetClass()) {
1519- // func = cr->GetMethodWithPrototype(name.c_str(), proto.c_str());
1520- // if (!func) {
1521- // cl = cr->GetClassInfo();
1522- // // try base classes to cover a common 'using' case (TODO: this is stupid and misses
1523- // // out on base classes; fix that with improved access to Cling)
1524- // TCppIndex_t nbases = GetNumBases(scope);
1525- // for (TCppIndex_t i = 0; i < nbases; ++i) {
1526- // TClassRef& base = type_from_handle(GetScope(GetBaseName(scope, i)));
1527- // if (base.GetClass()) {
1528- // func = base->GetMethodWithPrototype(name.c_str(), proto.c_str());
1529- // if (func) break;
1530- // }
1531- // }
1532- // }
1533- // }
1534- // }
1535- //
1536- // if (!func && name.back() == '>' && (cl || scope == (cppyy_scope_t)GLOBAL_HANDLE)) {
1537- // // try again, ignoring proto in case full name is complete template
1538- // auto declid = gInterpreter->GetFunction(cl, name.c_str());
1539- // if (declid) {
1540- // auto existing = gMethodTemplates.find(declid);
1541- // if (existing == gMethodTemplates.end()) {
1542- // auto cw = new_CallWrapper(declid, name);
1543- // existing = gMethodTemplates.insert(std::make_pair(declid, cw)).first;
1544- // }
1545- // return (TCppMethod_t)existing->second;
1546- // }
1547- // }
1548- //
1549- // if (func) {
1550- // // make sure we didn't match a non-templated overload
1551- // if (func->ExtraProperty() & kIsTemplateSpec)
1552- // return (TCppMethod_t)new_CallWrapper(func);
1553- //
1554- // // disregard this non-templated method as it will be considered when appropriate
1555- // return (TCppMethod_t)nullptr;
1556- // }
1557- //
1558- // // try again with template arguments removed from name, if applicable
1559- // if (name.back() == '>') {
1560- // auto pos = name.find('<');
1561- // if (pos != std::string::npos) {
1562- // TCppMethod_t cppmeth = GetMethodTemplate(scope, name.substr(0, pos), proto);
1563- // if (cppmeth) {
1564- // // allow if requested template names match up to the result
1565- // const std::string& alt = GetMethodFullName(cppmeth);
1566- // if (name.size() < alt.size() && alt.find('<') == pos) {
1567- // if (template_compare(name, alt))
1568- // return cppmeth;
1569- // }
1570- // }
1571- // }
1572- // }
1486+ std::string pureName;
1487+ std::string explicit_params;
1488+
1489+ if (name.find (' <' ) != std::string::npos) {
1490+ pureName = name.substr (0 , name.find (' <' ));
1491+ size_t start = name.find (' <' );
1492+ size_t end = name.find (' >' );
1493+ explicit_params = name.substr (start + 1 , end - start - 1 );
1494+ }
1495+
1496+ else pureName = name;
1497+
1498+ std::vector<Cppyy::TCppMethod_t> unresolved_candidate_methods;
1499+ Cpp::GetClassTemplatedMethods (pureName, scope,
1500+ unresolved_candidate_methods);
1501+
1502+ // CPyCppyy assumes that we attempt instantiation here
1503+ std::vector<Cpp::TemplateArgInfo> arg_types;
1504+ std::vector<Cpp::TemplateArgInfo> templ_params;
1505+ Cppyy::AppendTypesSlow (proto, arg_types);
1506+ Cppyy::AppendTypesSlow (explicit_params, templ_params);
1507+
1508+ Cppyy::TCppMethod_t cppmeth = Cpp::BestTemplateFunctionMatch (unresolved_candidate_methods, templ_params, arg_types);
1509+
1510+ if (!cppmeth){
1511+ return nullptr ;
1512+ }
1513+
1514+ return cppmeth;
1515+
1516+ // if it fails, use Sema to propogate info about why it failed (DeductionInfo)
15731517
1574- // failure ...
1575- return (TCppMethod_t)nullptr ;
15761518}
1519+
15771520//
15781521// static inline
15791522// std::string type_remap(const std::string& n1, const std::string& n2)
0 commit comments