@@ -1484,18 +1484,23 @@ Cppyy::TCppMethod_t Cppyy::GetMethodTemplate(
1484
1484
std::string pureName;
1485
1485
std::string explicit_params;
1486
1486
1487
- if (name.find (' <' ) != std::string::npos) {
1487
+ if ((name.find (" operator<" ) != 0 ) &&
1488
+ (name.find (' <' ) != std::string::npos)) {
1488
1489
pureName = name.substr (0 , name.find (' <' ));
1489
1490
size_t start = name.find (' <' );
1490
1491
size_t end = name.rfind (' >' );
1491
1492
explicit_params = name.substr (start + 1 , end - start - 1 );
1493
+ } else {
1494
+ pureName = name;
1492
1495
}
1493
1496
1494
- else pureName = name;
1495
-
1496
1497
std::vector<Cppyy::TCppMethod_t> unresolved_candidate_methods;
1497
1498
Cpp::GetClassTemplatedMethods (pureName, scope,
1498
1499
unresolved_candidate_methods);
1500
+ if (unresolved_candidate_methods.empty ()) {
1501
+ // try operators
1502
+ Cppyy::GetClassOperators (scope, pureName, unresolved_candidate_methods);
1503
+ }
1499
1504
1500
1505
// CPyCppyy assumes that we attempt instantiation here
1501
1506
std::vector<Cpp::TemplateArgInfo> arg_types;
@@ -1520,32 +1525,70 @@ Cppyy::TCppMethod_t Cppyy::GetMethodTemplate(
1520
1525
1521
1526
}
1522
1527
1523
- //
1524
- // static inline
1525
- // std::string type_remap(const std::string& n1, const std::string& n2)
1526
- // {
1527
- // // Operator lookups of (C++ string, Python str) should succeed for the combos of
1528
- // // string/str, wstring/str, string/unicode and wstring/unicode; since C++ does not have a
1529
- // // operator+(std::string, std::wstring), we'll have to look up the same type and rely on
1530
- // // the converters in CPyCppyy/_cppyy.
1531
- // if (n1 == "str" || n1 == "unicode") {
1532
- // if (n2 == "std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >")
1533
- // return n2; // match like for like
1534
- // return "std::string"; // probably best bet
1535
- // } else if (n1 == "float") {
1536
- // return "double"; // debatable, but probably intended
1537
- // } else if (n1 == "complex") {
1538
- // return "std::complex<double>";
1539
- // }
1540
- // return n1;
1541
- // }
1528
+ static inline std::string type_remap (const std::string& n1,
1529
+ const std::string& n2) {
1530
+ // Operator lookups of (C++ string, Python str) should succeed for the
1531
+ // combos of string/str, wstring/str, string/unicode and wstring/unicode;
1532
+ // since C++ does not have a operator+(std::string, std::wstring), we'll
1533
+ // have to look up the same type and rely on the converters in
1534
+ // CPyCppyy/_cppyy.
1535
+ if (n1 == " str" || n1 == " unicode" ) {
1536
+ // if (n2 ==
1537
+ // "std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t>
1538
+ // >")
1539
+ // return n2; // match like for like
1540
+ return " std::string" ; // probably best bet
1541
+ } else if (n1 == " float" ) {
1542
+ return " double" ; // debatable, but probably intended
1543
+ } else if (n1 == " complex" ) {
1544
+ return " std::complex<double>" ;
1545
+ }
1546
+ return n1;
1547
+ }
1548
+
1549
+ void Cppyy::GetClassOperators (Cppyy::TCppScope_t klass,
1550
+ const std::string& opname,
1551
+ std::vector<TCppScope_t>& operators) {
1552
+ if (opname == " operator+" )
1553
+ Cpp::GetOperator (klass, Cpp::Operator::OP_Plus, operators);
1554
+ else if (opname == " operator-" )
1555
+ Cpp::GetOperator (klass, Cpp::Operator::OP_Minus, operators);
1556
+ else if (opname == " operator*" )
1557
+ Cpp::GetOperator (klass, Cpp::Operator::OP_Star, operators);
1558
+ else if (opname == " operator/" )
1559
+ Cpp::GetOperator (klass, Cpp::Operator::OP_Slash, operators);
1560
+ else if (opname == " operator<" )
1561
+ Cpp::GetOperator (klass, Cpp::Operator::OP_Less, operators);
1562
+ else if (opname == " operator<=" )
1563
+ Cpp::GetOperator (klass, Cpp::Operator::OP_LessEqual, operators);
1564
+ else if (opname == " operator>" )
1565
+ Cpp::GetOperator (klass, Cpp::Operator::OP_Greater, operators);
1566
+ else if (opname == " operator>=" )
1567
+ Cpp::GetOperator (klass, Cpp::Operator::OP_GreaterEqual, operators);
1568
+ // FIXME: enabling `==` and `!=` requires friend operators
1569
+ // else if (opname == "operator==")
1570
+ // Cpp::GetOperator(klass, Cpp::Operator::OP_EqualEqual, operators);
1571
+ // else if (opname == "operator!=")
1572
+ // Cpp::GetOperator(klass, Cpp::Operator::OP_ExclaimEqual, operators);
1573
+ else if (opname == " operator<<" )
1574
+ Cpp::GetOperator (klass, Cpp::Operator::OP_LessLess, operators);
1575
+ else if (opname == " operator>>" )
1576
+ Cpp::GetOperator (klass, Cpp::Operator::OP_GreaterGreater, operators);
1577
+ else if (opname == " operator&" )
1578
+ Cpp::GetOperator (klass, Cpp::Operator::OP_Amp, operators);
1579
+ else if (opname == " operator|" )
1580
+ Cpp::GetOperator (klass, Cpp::Operator::OP_Pipe, operators);
1581
+ }
1542
1582
1543
1583
Cppyy::TCppMethod_t Cppyy::GetGlobalOperator (
1544
1584
TCppType_t scope, const std::string& lc, const std::string& rc, const std::string& opname)
1545
1585
{
1546
- if ((lc.find (' <' ) != std::string::npos) || (rc.find (' <' ) != std::string::npos)) {
1547
- // arguments of templated types
1548
- return nullptr ;
1586
+ std::string rc_type = type_remap (rc, lc);
1587
+ std::string lc_type = type_remap (lc, rc);
1588
+ bool is_templated = false ;
1589
+ if ((lc_type.find (' <' ) != std::string::npos) ||
1590
+ (rc_type.find (' <' ) != std::string::npos)) {
1591
+ is_templated = true ;
1549
1592
}
1550
1593
1551
1594
std::vector<TCppScope_t> overloads;
@@ -1565,10 +1608,11 @@ Cppyy::TCppMethod_t Cppyy::GetGlobalOperator(
1565
1608
Cpp::GetOperator (scope, Cpp::Operator::OP_Greater, overloads);
1566
1609
else if (opname == " >=" )
1567
1610
Cpp::GetOperator (scope, Cpp::Operator::OP_GreaterEqual, overloads);
1568
- else if (opname == " ==" )
1569
- Cpp::GetOperator (scope, Cpp::Operator::OP_EqualEqual, overloads);
1570
- else if (opname == " !=" )
1571
- Cpp::GetOperator (scope, Cpp::Operator::OP_ExclaimEqual, overloads);
1611
+ // FIXME: enabling `==` and `!=` requires friend operators
1612
+ // else if (opname == "==")
1613
+ // Cpp::GetOperator(scope, Cpp::Operator::OP_EqualEqual, overloads);
1614
+ // else if (opname == "!=")
1615
+ // Cpp::GetOperator(scope, Cpp::Operator::OP_ExclaimEqual, overloads);
1572
1616
else if (opname == " <<" )
1573
1617
Cpp::GetOperator (scope, Cpp::Operator::OP_LessLess, overloads);
1574
1618
else if (opname == " >>" )
@@ -1578,25 +1622,51 @@ Cppyy::TCppMethod_t Cppyy::GetGlobalOperator(
1578
1622
else if (opname == " |" )
1579
1623
Cpp::GetOperator (scope, Cpp::Operator::OP_Pipe, overloads);
1580
1624
1625
+ std::vector<Cppyy::TCppMethod_t> unresolved_candidate_methods;
1581
1626
for (auto overload: overloads) {
1582
- if (Cpp::IsTemplatedFunction (overload))
1627
+ if (Cpp::IsTemplatedFunction (overload)) {
1628
+ unresolved_candidate_methods.push_back (overload);
1583
1629
continue ;
1584
-
1585
- TCppType_t lhs_type = Cpp::GetFunctionArgType (overload, 0 );
1586
- if (lc != Cpp::GetTypeAsString (Cpp::GetUnderlyingType (lhs_type)))
1587
- continue ;
1588
-
1589
- if ((!rc.empty ()) && (Cpp::GetFunctionNumArgs (overload) == 2 )) {
1590
- TCppType_t rhs_type = Cpp::GetFunctionArgType (overload, 1 );
1591
- if (rc != Cpp::GetTypeAsString (Cpp::GetUnderlyingType (rhs_type)))
1592
- continue ;
1593
1630
} else {
1594
- continue ;
1595
- }
1631
+ TCppType_t lhs_type = Cpp::GetFunctionArgType (overload, 0 );
1632
+ if (lc_type !=
1633
+ Cpp::GetTypeAsString (Cpp::GetUnderlyingType (lhs_type)))
1634
+ continue ;
1596
1635
1597
- return overload;
1636
+ if (!rc_type.empty ()) {
1637
+ if (Cpp::GetFunctionNumArgs (overload) != 2 )
1638
+ continue ;
1639
+ TCppType_t rhs_type = Cpp::GetFunctionArgType (overload, 1 );
1640
+ if (rc_type !=
1641
+ Cpp::GetTypeAsString (Cpp::GetUnderlyingType (rhs_type)))
1642
+ continue ;
1643
+ }
1644
+ return overload;
1645
+ }
1646
+ }
1647
+ if (is_templated) {
1648
+ std::string lc_template = lc_type.substr (
1649
+ lc_type.find (" <" ) + 1 , lc_type.rfind (" >" ) - lc_type.find (" <" ) - 1 );
1650
+ std::string rc_template = rc_type.substr (
1651
+ rc_type.find (" <" ) + 1 , rc_type.rfind (" >" ) - rc_type.find (" <" ) - 1 );
1652
+
1653
+ std::vector<Cpp::TemplateArgInfo> arg_types;
1654
+ if (auto l = Cppyy::GetType (lc_type, true ))
1655
+ arg_types.emplace_back (l);
1656
+ else
1657
+ return nullptr ;
1658
+
1659
+ if (!rc_type.empty ()) {
1660
+ if (auto r = Cppyy::GetType (rc_type, true ))
1661
+ arg_types.emplace_back (r);
1662
+ else
1663
+ return nullptr ;
1664
+ }
1665
+ Cppyy::TCppMethod_t cppmeth = Cpp::BestOverloadFunctionMatch (
1666
+ unresolved_candidate_methods, {}, arg_types);
1667
+ if (cppmeth)
1668
+ return cppmeth;
1598
1669
}
1599
-
1600
1670
return nullptr ;
1601
1671
}
1602
1672
0 commit comments