Commits

wlav committed a2be4d1

consolidate overload tests with CPython/cppyy and add void* use for unknown classes

  • Participants
  • Parent commits f797859
  • Branches reflex-support

Comments (0)

Files changed (7)

File pypy/module/cppyy/converter.py

         if compound == "&":
             return _converters['const unsigned int&'](space, default)
         return _converters['unsigned int'](space, default)
+    elif compound:
+        # "user knows best": allow any ref or ptr unchecked as-if it was void*
+        # TODO: issue python warning
+        return _converters['void*'](space, name)
 
     #   5) void converter, which fails on use
     #

File pypy/module/cppyy/interp_cppyy.py

     pass
 
 # overload priorities: lower is preferred
-priority = { 'void*'  : 100,
-             'void**' : 100,
-             'float'  :  30,
-             'double' :  10, }
+priority = { 'void*'       : 100,
+             'void**'      : 100,
+             'float'       :  30,
+             'long double' :  15,
+             'double'      :  10, }
 
 from rpython.rlib.listsort import make_timsort_class
 CPPMethodBaseTimSort = make_timsort_class()
         if self.converters is None:
             try:
                 self._setup(cppthis)
-            except Exception, e:
+            except Exception:
                 pass
 
         # some calls, e.g. for ptr-ptr or reference need a local array to store data for
                 self.uses_local = True
                 break
 
+        return
         # Each CPPMethod corresponds one-to-one to a C++ equivalent and cppthis
         # has been offset to the matching class. Hence, the libffi pointer is
         # uniquely defined and needs to be setup only once.
 
     def priority(self):
         total_arg_priority = 0
-        for p in [priority.get(arg_type, 0) for arg_type, arg_dflt in self.arg_defs]:
-            total_arg_priority += p
+        for arg_type, arg_dflt in self.arg_defs:
+            try:
+                total_arg_priority += priority[arg_type]
+            except KeyError:
+                if arg_type[-1] == '&':      # causes ptr preference over ref
+                    total_arg_priority += 1
         return total_arg_priority
 
     def __del__(self):
         for f in overload.functions:
             if 0 < f.signature().find(sig):
                 return W_CPPOverload(self.space, self, [f])
-        raise OperationError(self.space.w_TypeError, self.space.wrap("no overload matches signature"))
+        raise OperationError(self.space.w_LookupError, self.space.wrap("no overload matches signature"))
 
     def missing_attribute_error(self, name):
         return OperationError(

File pypy/module/cppyy/test/overloads.cxx

 #include "overloads.h"
 
 
-a_overload::a_overload() { i1 = 42; i2 = -1; }
+//===========================================================================
+OverloadA::OverloadA() { i1 = 42; i2 = -1; }
 
-ns_a_overload::a_overload::a_overload() { i1 = 88; i2 = -34; }
-int ns_a_overload::b_overload::f(const std::vector<int>* v) { return (*v)[0]; }
+NamespaceA::OverloadA::OverloadA() { i1 = 88; i2 = -34; }
+int NamespaceA::OverloadB::f(const std::vector<int>* v) { return (*v)[0]; }
 
-ns_b_overload::a_overload::a_overload() { i1 = -33; i2 = 89; }
+NamespaceB::OverloadA::OverloadA() { i1 = -33; i2 = 89; }
 
-b_overload::b_overload() { i1 = -2; i2 = 13; }
+OverloadB::OverloadB() { i1 = -2; i2 = 13; }
 
-c_overload::c_overload() {}
-int c_overload::get_int(a_overload* a)                { return a->i1; }
-int c_overload::get_int(ns_a_overload::a_overload* a) { return a->i1; }
-int c_overload::get_int(ns_b_overload::a_overload* a) { return a->i1; }
-int c_overload::get_int(short* p)                     { return *p; }
-int c_overload::get_int(b_overload* b)                { return b->i2; }
-int c_overload::get_int(int* p)                       { return *p; }
 
-d_overload::d_overload() {}
-int d_overload::get_int(int* p)                       { return *p; }
-int d_overload::get_int(b_overload* b)                { return b->i2; }
-int d_overload::get_int(short* p)                     { return *p; }
-int d_overload::get_int(ns_b_overload::a_overload* a) { return a->i1; }
-int d_overload::get_int(ns_a_overload::a_overload* a) { return a->i1; }
-int d_overload::get_int(a_overload* a)                { return a->i1; }
+//===========================================================================
+OverloadC::OverloadC() {}
+int OverloadC::get_int(OverloadA* a)                 { return a->i1; }
+int OverloadC::get_int(NamespaceA::OverloadA* a)     { return a->i1; }
+int OverloadC::get_int(NamespaceB::OverloadA* a)     { return a->i1; }
+int OverloadC::get_int(short* p)                     { return *p; }
+int OverloadC::get_int(OverloadB* b)                 { return b->i2; }
+int OverloadC::get_int(int* p)                       { return *p; }
 
 
-more_overloads::more_overloads() {}
-std::string more_overloads::call(const aa_ol&) { return "aa_ol"; }
-std::string more_overloads::call(const bb_ol&, void* n) { n = 0; return "bb_ol"; }
-std::string more_overloads::call(const cc_ol&) { return "cc_ol"; }
-std::string more_overloads::call(const dd_ol&) { return "dd_ol"; }
+//===========================================================================
+OverloadD::OverloadD() {}
+int OverloadD::get_int(int* p)                       { return *p; }
+int OverloadD::get_int(OverloadB* b)                 { return b->i2; }
+int OverloadD::get_int(short* p)                     { return *p; }
+int OverloadD::get_int(NamespaceB::OverloadA* a)     { return a->i1; }
+int OverloadD::get_int(NamespaceA::OverloadA* a)     { return a->i1; }
+int OverloadD::get_int(OverloadA* a)                 { return a->i1; }
 
-std::string more_overloads::call_unknown(const dd_ol&) { return "dd_ol"; }
 
-std::string more_overloads::call(double)  { return "double"; }
-std::string more_overloads::call(int)     { return "int"; }
-std::string more_overloads::call1(int)    { return "int"; }
-std::string more_overloads::call1(double) { return "double"; }
+//===========================================================================
+OlBB* get_OlBB() { return (OlBB*)0; }
+OlDD* get_OlDD() { return (OlDD*)0; }
 
 
-more_overloads2::more_overloads2() {}
-std::string more_overloads2::call(const bb_ol&) { return "bb_olref"; }
-std::string more_overloads2::call(const bb_ol*) { return "bb_olptr"; }
+//===========================================================================
+MoreOverloads::MoreOverloads() {}
+std::string MoreOverloads::call(const OlAA&) { return "OlAA"; }
+std::string MoreOverloads::call(const OlBB&, void* n) { n = 0; return "OlBB"; }
+std::string MoreOverloads::call(const OlCC&) { return "OlCC"; }
+std::string MoreOverloads::call(const OlDD&) { return "OlDD"; }
 
-std::string more_overloads2::call(const dd_ol*, int) { return "dd_olptr"; }
-std::string more_overloads2::call(const dd_ol&, int) { return "dd_olref"; }
+std::string MoreOverloads::call_unknown(const OlDD&) { return "OlDD"; }
 
+std::string MoreOverloads::call(double)  { return "double"; }
+std::string MoreOverloads::call(int)     { return "int"; }
+std::string MoreOverloads::call1(int)    { return "int"; }
+std::string MoreOverloads::call1(double) { return "double"; }
 
-double calc_mean(long n, const float* a)     { return calc_mean<float>(n, a); }
-double calc_mean(long n, const double* a)    { return calc_mean<double>(n, a); }
-double calc_mean(long n, const int* a)       { return calc_mean<int>(n, a); }
-double calc_mean(long n, const short* a)     { return calc_mean<short>(n, a); }
-double calc_mean(long n, const long* a)      { return calc_mean<long>(n, a); }
+
+//===========================================================================
+MoreOverloads2::MoreOverloads2() {}
+std::string MoreOverloads2::call(const OlBB&) { return "OlBB&"; }
+std::string MoreOverloads2::call(const OlBB*) { return "OlBB*"; }
+
+std::string MoreOverloads2::call(const OlDD*, int) { return "OlDD*"; }
+std::string MoreOverloads2::call(const OlDD&, int) { return "OlDD&"; }
+
+
+//===========================================================================
+double calc_mean(long n, const float* a)  { return calc_mean_templ<float>(n, a); }
+double calc_mean(long n, const double* a) { return calc_mean_templ<double>(n, a); }
+double calc_mean(long n, const int* a)    { return calc_mean_templ<int>(n, a); }
+double calc_mean(long n, const short* a)  { return calc_mean_templ<short>(n, a); }
+double calc_mean(long n, const long* a)   { return calc_mean_templ<long>(n, a); }

File pypy/module/cppyy/test/overloads.h

 #include <string>
 #include <vector>
 
-class a_overload {
+
+//===========================================================================
+class OverloadA {
 public:
-    a_overload();
+    OverloadA();
     int i1, i2;
 };
 
-namespace ns_a_overload {
-    class a_overload {
+namespace NamespaceA {
+    class OverloadA {
     public:
-        a_overload();
+        OverloadA();
         int i1, i2;
     };
 
-    class b_overload {
+    class OverloadB {
     public:
         int f(const std::vector<int>* v);
     };
 }
 
-namespace ns_b_overload {
-    class a_overload {
+namespace NamespaceB {
+    class OverloadA {
     public:
-        a_overload();
+        OverloadA();
         int i1, i2;
     };
 }
 
-class b_overload {
+class OverloadB {
 public:
-    b_overload();
+    OverloadB();
     int i1, i2;
 };
 
-class c_overload {
+
+//===========================================================================
+class OverloadC {
 public:
-    c_overload();
-    int get_int(a_overload* a);
-    int get_int(ns_a_overload::a_overload* a);
-    int get_int(ns_b_overload::a_overload* a);
+    OverloadC();
+    int get_int(OverloadA* a);
+    int get_int(NamespaceA::OverloadA* a);
+    int get_int(NamespaceB::OverloadA* a);
     int get_int(short* p);
-    int get_int(b_overload* b);
+    int get_int(OverloadB* b);
     int get_int(int* p);
 };
 
-class d_overload {
+
+//===========================================================================
+class OverloadD {
 public:
-    d_overload();
+    OverloadD();
 //   int get_int(void* p) { return *(int*)p; }
     int get_int(int* p);
-    int get_int(b_overload* b);
+    int get_int(OverloadB* b);
     int get_int(short* p);
-    int get_int(ns_b_overload::a_overload* a);
-    int get_int(ns_a_overload::a_overload* a);
-    int get_int(a_overload* a);
+    int get_int(NamespaceB::OverloadA* a);
+    int get_int(NamespaceA::OverloadA* a);
+    int get_int(OverloadA* a);
 };
 
 
-class aa_ol {};
-class bb_ol;
-class cc_ol {};
-class dd_ol;
+//===========================================================================
+class OlAA {};
+class OlBB;
+struct OlCC {};
+struct OlDD;
 
-class more_overloads {
+OlBB* get_OlBB();
+OlDD* get_OlDD();
+
+
+//===========================================================================
+class MoreOverloads {
 public:
-    more_overloads();
-    std::string call(const aa_ol&);
-    std::string call(const bb_ol&, void* n=0);
-    std::string call(const cc_ol&);
-    std::string call(const dd_ol&);
+    MoreOverloads();
+    std::string call(const OlAA&);
+    std::string call(const OlBB&, void* n=0);
+    std::string call(const OlCC&);
+    std::string call(const OlDD&);
 
-    std::string call_unknown(const dd_ol&);
+    std::string call_unknown(const OlDD&);
 
     std::string call(double);
     std::string call(int);
     std::string call1(double);
 };
 
-class more_overloads2 {
+
+//===========================================================================
+class MoreOverloads2 {
 public:
-    more_overloads2();
-    std::string call(const bb_ol&);
-    std::string call(const bb_ol*);
+    MoreOverloads2();
+    std::string call(const OlBB&);
+    std::string call(const OlBB*);
 
-    std::string call(const dd_ol*, int);
-    std::string call(const dd_ol&, int);
+    std::string call(const OlDD*, int);
+    std::string call(const OlDD&, int);
 };
 
+
+//===========================================================================
+double calc_mean(long n, const float* a);
+double calc_mean(long n, const double* a);
+double calc_mean(long n, const int* a);
+double calc_mean(long n, const short* a);
+double calc_mean(long n, const long* a);
+
 template<typename T>
-double calc_mean(long n, const T* a) {
+double calc_mean_templ(long n, const T* a) {
     double sum = 0., sumw = 0.;
     const T* end = a+n;
     while (a != end) {
     return sum/sumw;
 }
 
-double calc_mean(long n, const float* a);
-double calc_mean(long n, const double* a);
-double calc_mean(long n, const int* a);
-double calc_mean(long n, const short* a);
-double calc_mean(long n, const long* a);
+template double calc_mean_templ<float> (long, const float*);
+template double calc_mean_templ<double>(long, const double*);
+template double calc_mean_templ<int>   (long, const int*);
+template double calc_mean_templ<short> (long, const short*);
+template double calc_mean_templ<long>  (long, const long*);
+
+
+//===========================================================================
+#define STLTYPE_INSTANTIATION(STLTYPE, TTYPE, N)                             \
+   std::STLTYPE<TTYPE > STLTYPE##_##N;                                       \
+   std::STLTYPE<TTYPE >::iterator STLTYPE##_##N##_i;                         \
+   std::STLTYPE<TTYPE >::const_iterator STLTYPE##_##N##_ci
+
+#define STLTYPE_INSTANTIATION2(STLTYPE, TTYPE1, TTYPE2, N)                   \
+   std::STLTYPE<TTYPE1, TTYPE2 > STLTYPE##_##N;                              \
+   std::pair<TTYPE1, TTYPE2 > STLTYPE##_##N##_p;                             \
+   std::pair<const TTYPE1, TTYPE2 > STLTYPE##_##N##_cp;                      \
+   std::STLTYPE<TTYPE1, TTYPE2 >::iterator STLTYPE##_##N##_i;                \
+   std::STLTYPE<TTYPE1, TTYPE2 >::const_iterator STLTYPE##_##N##_ci
+
+
+namespace {
+
+    struct _CppyyVectorInstances {
+
+        STLTYPE_INSTANTIATION(vector, int,          1);
+
+    };
+
+}

File pypy/module/cppyy/test/overloads.xml

 <lcgdict>
 
   <class name="std::string" />
+  <class name="std::vector<int>" />
 
-  <class pattern="*_overload" />
+  <class pattern="Overload*" />
 
-  <namespace pattern="ns_*_overload" />
-  <class pattern="ns_*_overload::*_overload" />
+  <namespace pattern="Namespace*" />
+  <class pattern="Namespace*::Overload*" />
 
-  <class pattern="*_ol" />
-  <class name="more_overloads" />
-  <class name="more_overloads2" />
+  <class pattern="Ol*" />
+  <!-- need to be explicit for the forward declared class returns -->
+  <function name="get_OlBB" />
+  <function name="get_OlDD" />
+
+  <class name="MoreOverloads" />
+  <class name="MoreOverloads2" />
 
   <function name="calc_mean" />
+  <function pattern="calc_mean_templ<*>" />
 
 </lcgdict>

File pypy/module/cppyy/test/overloads_LinkDef.h

 #pragma link off all classes;
 #pragma link off all functions;
 
-#pragma link C++ class a_overload;
-#pragma link C++ class b_overload;
-#pragma link C++ class c_overload;
-#pragma link C++ class d_overload;
+#pragma link C++ class OverloadA;
+#pragma link C++ class OverloadB;
+#pragma link C++ class OverloadC;
+#pragma link C++ class OverloadD;
 
-#pragma link C++ namespace ns_a_overload;
-#pragma link C++ class ns_a_overload::a_overload;
-#pragma link C++ class ns_a_overload::b_overload;
+#pragma link C++ namespace NamespaceA;
+#pragma link C++ class NamespaceA::OverloadA;
+#pragma link C++ class NamespaceA::OverloadB;
 
-#pragma link C++ class ns_b_overload;
-#pragma link C++ class ns_b_overload::a_overload;
+#pragma link C++ class NamespaceB;
+#pragma link C++ class NamespaceB::OverloadA;
 
-#pragma link C++ class aa_ol;
-#pragma link C++ class cc_ol;
+#pragma link C++ class OlAA;
+#pragma link C++ class OlCC;
+#pragma link C++ function get_OlBB;
+#pragma link C++ function get_OlDD;
 
-#pragma link C++ class more_overloads;
-#pragma link C++ class more_overloads2;
+#pragma link C++ class MoreOverloads;
+#pragma link C++ class MoreOverloads2;
 
 #pragma link C++ function calc_mean;
+#pragma link C++ function calc_mean_templ<float>;
+#pragma link C++ function calc_mean_templ<double>;
+#pragma link C++ function calc_mean_templ<int>;
+#pragma link C++ function calc_mean_templ<short>;
+#pragma link C++ function calc_mean_templ<long>;
 
 #endif

File pypy/module/cppyy/test/test_overloads.py

             return cppyy.load_reflection_info(%r)""" % (test_dct, ))
 
     def test01_class_based_overloads(self):
-        """Test functions overloaded on different C++ clases"""
+        """Functions overloaded on different C++ class arguments"""
 
         import cppyy
-        a_overload = cppyy.gbl.a_overload
-        b_overload = cppyy.gbl.b_overload
-        c_overload = cppyy.gbl.c_overload
-        d_overload = cppyy.gbl.d_overload
+        OverloadA = cppyy.gbl.OverloadA
+        OverloadB = cppyy.gbl.OverloadB
+        OverloadC = cppyy.gbl.OverloadC
+        OverloadD = cppyy.gbl.OverloadD
 
-        ns_a_overload = cppyy.gbl.ns_a_overload
-        ns_b_overload = cppyy.gbl.ns_b_overload
+        NamespaceA = cppyy.gbl.NamespaceA
+        NamespaceB = cppyy.gbl.NamespaceB
 
-        assert c_overload().get_int(a_overload()) == 42
-        assert c_overload().get_int(b_overload()) == 13
-        assert d_overload().get_int(a_overload()) == 42
-        assert d_overload().get_int(b_overload()) == 13
+        assert OverloadC().get_int(OverloadA()) == 42
+        assert OverloadC().get_int(OverloadB()) == 13
+        assert OverloadD().get_int(OverloadA()) == 42
+        assert OverloadD().get_int(OverloadB()) == 13
 
-        assert c_overload().get_int(ns_a_overload.a_overload()) ==  88
-        assert c_overload().get_int(ns_b_overload.a_overload()) == -33
+        assert OverloadC().get_int(NamespaceA.OverloadA()) ==  88
+        assert OverloadC().get_int(NamespaceB.OverloadA()) == -33
 
-        assert d_overload().get_int(ns_a_overload.a_overload()) ==  88
-        assert d_overload().get_int(ns_b_overload.a_overload()) == -33
+        assert OverloadD().get_int(NamespaceA.OverloadA()) ==  88
+        assert OverloadD().get_int(NamespaceB.OverloadA()) == -33
 
     def test02_class_based_overloads_explicit_resolution(self):
-        """Test explicitly resolved function overloads"""
+        """Explicitly resolved function overloads"""
 
         import cppyy
-        a_overload = cppyy.gbl.a_overload
-        b_overload = cppyy.gbl.b_overload
-        c_overload = cppyy.gbl.c_overload
-        d_overload = cppyy.gbl.d_overload
+        OverloadA = cppyy.gbl.OverloadA
+        OverloadB = cppyy.gbl.OverloadB
+        OverloadC = cppyy.gbl.OverloadC
+        OverloadD = cppyy.gbl.OverloadD
 
-        ns_a_overload = cppyy.gbl.ns_a_overload
+        NamespaceA = cppyy.gbl.NamespaceA
 
-        c = c_overload()
+        c = OverloadC()
         raises(TypeError, c.__dispatch__, 'get_int', 12)
-        raises(TypeError, c.__dispatch__, 'get_int', 'does_not_exist')
-        assert c.__dispatch__('get_int', 'a_overload*')(a_overload()) == 42
-        assert c.__dispatch__('get_int', 'b_overload*')(b_overload()) == 13
+        raises(LookupError, c.__dispatch__, 'get_int', 'does_not_exist')
+        assert c.__dispatch__('get_int', 'OverloadA*')(OverloadA()) == 42
+        assert c.__dispatch__('get_int', 'OverloadB*')(OverloadB()) == 13
 
-        assert c_overload().__dispatch__('get_int', 'a_overload*')(a_overload())  == 42
-        # TODO: #assert c_overload.__dispatch__('get_int', 'b_overload*')(c, b_overload()) == 13
+        assert OverloadC().__dispatch__('get_int', 'OverloadA*')(OverloadA())  == 42
+        # TODO: #assert c_overload.__dispatch__('get_int', 'OverloadB*')(c, OverloadB()) == 13
 
-        d = d_overload()
-        assert d.__dispatch__('get_int', 'a_overload*')(a_overload()) == 42
-        assert d.__dispatch__('get_int', 'b_overload*')(b_overload()) == 13
+        d = OverloadD()
+        assert d.__dispatch__('get_int', 'OverloadA*')(OverloadA()) == 42
+        assert d.__dispatch__('get_int', 'OverloadB*')(OverloadB()) == 13
 
-        nb = ns_a_overload.b_overload()
-        raises(TypeError, nb.f, c_overload())
+        nb = NamespaceA.OverloadB()
+        raises(TypeError, nb.f, OverloadC())
 
     def test03_fragile_class_based_overloads(self):
         """Test functions overloaded on void* and non-existing classes"""
         # TODO: make Reflex generate unknown classes ...
 
         import cppyy
-        more_overloads = cppyy.gbl.more_overloads
-        aa_ol = cppyy.gbl.aa_ol
-#        bb_ol = cppyy.gbl.bb_ol
-        cc_ol = cppyy.gbl.cc_ol
-#        dd_ol = cppyy.gbl.dd_ol
+        MoreOverloads = cppyy.gbl.MoreOverloads
 
-        assert more_overloads().call(aa_ol()) == "aa_ol"
-#        assert more_overloads().call(bb_ol()) == "dd_ol"    # <- bb_ol has an unknown + void*
-        assert more_overloads().call(cc_ol()) == "cc_ol"
-#        assert more_overloads().call(dd_ol()) == "dd_ol"    # <- dd_ol has an unknown
+        OlAA = cppyy.gbl.OlAA
+#       OlBB = cppyy.gbl.OlBB
+        OlCC = cppyy.gbl.OlCC
+#       OlDD = cppyy.gbl.OlDD
+
+        from cppyy.gbl import get_OlBB, get_OlDD
+
+        # first verify that BB and DD are indeed unknown
+#       raises(RuntimeError, OlBB)
+#       raises(RuntimeError, OlDD )
+
+        # then try overloads based on them
+        assert MoreOverloads().call(OlAA())     == "OlAA"
+        assert MoreOverloads().call(get_OlBB()) == "OlDD"   # <- has an unknown + void*
+        assert MoreOverloads().call(OlCC())     == "OlCC"
+        assert MoreOverloads().call(get_OlDD()) == "OlDD"   # <- has an unknown
 
     def test04_fully_fragile_overloads(self):
-        """Test that unknown* is preferred over unknown&"""
-
-        # TODO: make Reflex generate unknown classes ...
-        return
+        """An unknown* is preferred over unknown&"""
 
         import cppyy
-        more_overloads2 = cppyy.gbl.more_overloads2
-        bb_ol = cppyy.gbl.bb_ol
-        dd_ol = cppyy.gbl.dd_ol
+        MoreOverloads2 = cppyy.gbl.MoreOverloads2
 
-        assert more_overloads2().call(bb_ol())    == "bb_olptr"
-        assert more_overloads2().call(dd_ol(), 1) == "dd_olptr"
+        from cppyy.gbl import get_OlBB, get_OlDD
+
+        assert MoreOverloads2().call(get_OlBB())    == "OlBB*"
+        assert MoreOverloads2().call(get_OlDD(), 1) == "OlDD*"
 
     def test05_array_overloads(self):
-        """Test functions overloaded on different arrays"""
+        """Functions overloaded on different arrays"""
 
         import cppyy
-        c_overload = cppyy.gbl.c_overload
-        d_overload = cppyy.gbl.d_overload
+        OverloadC = cppyy.gbl.OverloadC
+        OverloadD = cppyy.gbl.OverloadD
 
         from array import array
 
         ai = array('i', [525252])
-        assert c_overload().get_int(ai) == 525252
-        assert d_overload().get_int(ai) == 525252
+        assert OverloadC().get_int(ai) == 525252
+        assert OverloadD().get_int(ai) == 525252
 
         ah = array('h', [25])
-        assert c_overload().get_int(ah) == 25
-        assert d_overload().get_int(ah) == 25
+        assert OverloadC().get_int(ah) == 25
+        assert OverloadD().get_int(ah) == 25
 
     def test06_double_int_overloads(self):
-        """Test overloads on int/doubles"""
+        """Overloads on int/doubles"""
 
         import cppyy
-        more_overloads = cppyy.gbl.more_overloads
+        MoreOverloads = cppyy.gbl.MoreOverloads
 
-        assert more_overloads().call(1)   == "int"
-        assert more_overloads().call(1.)  == "double"
-        assert more_overloads().call1(1)  == "int"
-        assert more_overloads().call1(1.) == "double"
+        assert MoreOverloads().call(1)   == "int"
+        assert MoreOverloads().call(1.)  == "double"
+        assert MoreOverloads().call1(1)  == "int"
+        assert MoreOverloads().call1(1.) == "double"
 
     def test07_mean_overloads(self):
         """Adapted test for array overloading"""
         for l in ['f', 'd', 'i', 'h', 'l']:
             a = array.array(l, numbers)
             assert round(cmean(len(a), a) - mean, 8) == 0
+
+    def test08_templated_mean_overloads(self):
+        """Adapted test for array overloading with templates"""
+
+        import cppyy, array
+        cmean = cppyy.gbl.calc_mean_templ
+
+        numbers = [8, 2, 4, 2, 4, 2, 4, 4, 1, 5, 6, 3, 7]
+        mean, median = 4.0, 4.0
+
+        for l in ['f', 'd', 'i', 'h', 'l']:
+            a = array.array(l, numbers)
+            assert round(cmean(len(a), a) - mean, 8) == 0