Author: Wim Lavrijsen <[email protected]>
Branch: cppyy-dev
Changeset: r98049:47555bb4c1cc
Date: 2019-11-13 11:50 -0800
http://bitbucket.org/pypy/pypy/changeset/47555bb4c1cc/

Log:    prepare for more template tests

diff --git a/pypy/module/_cppyy/interp_cppyy.py 
b/pypy/module/_cppyy/interp_cppyy.py
--- a/pypy/module/_cppyy/interp_cppyy.py
+++ b/pypy/module/_cppyy/interp_cppyy.py
@@ -981,8 +981,8 @@
 )
 
 class W_CPPTemplateStaticOverload(W_CPPStaticOverload, TemplateOverloadMixin):
-    """App-level dispatcher to allow both lookup/instantiation of templated 
methods and
-    dispatch among overloads between templated and non-templated method."""
+    """Dispatcher to allow both lookup/instantiation of templated methods and
+    select among templated and non-templated method overloads."""
 
     _attrs_ = ['name', 'tmpl_args', 'overloads', 'master', 'w_this']
     _immutable_fields_ = ['name', 'tmpl_args']
@@ -996,7 +996,8 @@
          self.w_this = space.w_None
 
     def clone(self, tmpl_args):
-        other = W_CPPTemplateStaticOverload(self.space, self.name, tmpl_args, 
self.scope, self.functions, self.flags)
+        other = W_CPPTemplateStaticOverload(self.space, self.name,
+            tmpl_args, self.scope, self.functions, self.flags)
         other.overloads = self.overloads
         other.master = self.master
         other.w_this = self.w_this
@@ -1007,7 +1008,8 @@
         if isinstance(w_cppinstance, W_CPPInstance):
             cppinstance = self.space.interp_w(W_CPPInstance, w_cppinstance)
             if cppinstance.clsdecl.handle != self.scope.handle:
-                cppol = W_CPPTemplateStaticOverload(self.space, self.name, 
self.tmpl_args, self.scope, self.functions, self.flags)
+                cppol = W_CPPTemplateStaticOverload(self.space, self.name,
+                    self.tmpl_args, self.scope, self.functions, self.flags)
                 cppol.w_this = w_cppinstance
                 cppol.master = self.master
                 return cppol       # bound
@@ -1256,10 +1258,10 @@
         return self.handle != other.handle
 
 
-# For now, keep namespaces and classes separate as namespaces are extensible
+# Namespaces and classes are separate as namespaces are (more) extensible
 # with info from multiple dictionaries and do not need to bother with meta
-# classes for inheritance. Both are python classes, though, and refactoring
-# may be in order at some point.
+# classes for inheritance. Both are python classes, though, and further
+# refactoring may be in order at some point.
 class W_CPPNamespaceDecl(W_CPPScopeDecl):
     _attrs_ = ['space', 'handle', 'name', 'overloads', 'datamembers']
     _immutable_fields_ = ['handle', 'name']
diff --git a/pypy/module/_cppyy/test/templates.cxx 
b/pypy/module/_cppyy/test/templates.cxx
--- a/pypy/module/_cppyy/test/templates.cxx
+++ b/pypy/module/_cppyy/test/templates.cxx
@@ -10,3 +10,28 @@
 long MyTemplatedMethodClass::get_float_size()  { return (long)sizeof(float); }
 long MyTemplatedMethodClass::get_double_size() { return (long)sizeof(double); }
 long MyTemplatedMethodClass::get_self_size()   { return 
(long)sizeof(MyTemplatedMethodClass); }
+
+
+// variadic templates
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+std::string some_variadic::gTypeName = "";
+
+
+// template with empty body
+namespace T_WithEmptyBody {
+
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+std::string side_effect = "not set";
+
+template<typename T>
+void some_empty() {
+    side_effect = "side effect";
+}
+
+template void some_empty<int>();
+
+} // namespace T_WithRValue
diff --git a/pypy/module/_cppyy/test/templates.h 
b/pypy/module/_cppyy/test/templates.h
--- a/pypy/module/_cppyy/test/templates.h
+++ b/pypy/module/_cppyy/test/templates.h
@@ -1,12 +1,33 @@
+#ifndef CPPYY_TEST_TEMPLATES_H
+#define CPPYY_TEST_TEMPLATES_H
+
+#include <stdexcept>
 #include <string>
 #include <sstream>
 #include <vector>
 
+#ifndef WIN32
+#include <cxxabi.h>
+inline std::string demangle_it(const char* name, const char* errmsg) {
+    int status;
+    std::string res = abi::__cxa_demangle(name, 0, 0, &status);
+    if (status != 0) throw std::runtime_error(errmsg);
+    return res;
+}
+#else
+inline std::string demangle_it(const char* name, const char*) {
+    return name;        // typeinfo's name() is already demangled
+}
+#endif
+
 
 //===========================================================================
 class MyTemplatedMethodClass {         // template methods
 public:
-    long get_size();      // to get around bug in genreflex
+    template<class A> long get_size(A&);
+    template<class A> long get_size(const A&);
+
+    long get_size();
     template<class B> long get_size();
 
     long get_char_size();
@@ -21,6 +42,16 @@
     double m_data[3];
 };
 
+template<class A>
+long MyTemplatedMethodClass::get_size(A&) {
+    return sizeof(A);
+}
+
+template<class A>
+long MyTemplatedMethodClass::get_size(const A&) {
+    return sizeof(A)+1;
+}
+
 template<class B>
 inline long MyTemplatedMethodClass::get_size() {
     return sizeof(B);
@@ -63,7 +94,7 @@
 };
 
 template <class I, typename O = float>
-SomeResult<O> global_get_some_result(const std::vector<I>& carrier) {
+SomeResult<O> global_get_some_result(const I& carrier) {
     SomeResult<O> r{};
     r.m_retval = O(carrier[0]);
     return r;
@@ -156,3 +187,295 @@
     T m_value;
 };
 */
+
+
+//===========================================================================
+// templated callable
+class TemplatedCallable {
+public:
+    template <class I , class O = double>
+    O operator() (const I& in) const { return O(in); }
+};
+
+
+//===========================================================================
+// templated typedefs
+namespace TemplatedTypedefs {
+
+template<typename TYPE_IN, typename TYPE_OUT, size_t _vsize = 4>
+struct BaseWithEnumAndTypedefs {
+    enum { vsize = _vsize };
+    typedef TYPE_IN in_type;
+    typedef TYPE_OUT out_type;
+};
+
+template <typename TYPE_IN, typename TYPE_OUT, size_t _vsize = 4>
+struct DerivedWithUsing : public BaseWithEnumAndTypedefs<TYPE_IN, TYPE_OUT, 
_vsize>
+{
+    typedef BaseWithEnumAndTypedefs<TYPE_IN, TYPE_OUT, _vsize> base_type;
+    using base_type::vsize;
+    using typename base_type::in_type;
+    typedef typename base_type::in_type in_type_tt;
+    using typename base_type::out_type;
+};
+
+struct SomeDummy {};
+
+} // namespace TemplatedTypedefs
+
+
+//===========================================================================
+// hiding templated methods
+namespace TemplateHiding {
+
+struct Base {
+    template<class T>
+    int callme(T t = T(1)) { return 2*t; }
+};
+
+struct Derived : public Base {
+    int callme(int t = 2) { return t; }
+};
+
+} // namespace TemplateHiding
+
+
+//===========================================================================
+// 'using' of templates
+template<typename T> using DA_vector = std::vector<T>;
+
+#if __cplusplus > 201402L
+namespace using_problem {
+
+template <typename T, size_t SZ>
+struct vector {
+    vector() : m_val(SZ) {}
+    T m_val;
+};
+
+template <typename T, size_t ... sizes>
+struct matryoshka {
+    typedef T type;
+};
+
+template <typename T, size_t SZ, size_t ... sizes>
+struct matryoshka<T, SZ, sizes ... > {
+    typedef vector<typename matryoshka<T, sizes ...>::type, SZ> type;
+};
+
+template <typename T, size_t ... sizes>
+using make_vector = typename matryoshka<T, sizes ...>::type;
+    typedef make_vector<int, 2, 3> iiv_t;
+};
+#endif
+
+namespace using_problem {
+
+template<typename T>
+class Base {
+public:
+    template<typename R>
+    R get1(T t) { return t + R{5}; }
+    T get2() { return T{5}; }
+    template<typename R>
+    R get3(T t) { return t + R{5}; }
+    T get3() { return T{5}; }
+};
+
+template<typename T>
+class Derived : public Base<T> {
+public:
+    typedef Base<T> _Mybase;
+    using _Mybase::get1;
+    using _Mybase::get2;
+    using _Mybase::get3;
+};
+
+} // namespace using_problem
+
+
+//===========================================================================
+// template with r-value
+namespace T_WithRValue {
+
+template<typename T>
+bool is_valid(T&& new_value) {
+    return new_value != T{};
+}
+
+} // namespace T_WithRValue
+
+
+//===========================================================================
+// variadic templates
+namespace some_variadic {
+
+#ifdef WIN32
+extern __declspec(dllimport) std::string gTypeName;
+#else
+extern std::string gTypeName;
+#endif
+
+template <typename ... Args>
+class A {
+public:
+    A() {
+        gTypeName = demangle_it(typeid(A<Args...>).name(), "A::A");
+    }
+    A(const A&) = default;
+    A(A&&) = default;
+    A& operator=(const A&) = default;
+    A& operator=(A&&) = default;
+
+    template <typename ... FArgs>
+    void a(FArgs&&... args) {
+        gTypeName = demangle_it(typeid(&A<Args...>::a<FArgs...>).name(), 
"A::a-2");
+    }
+
+    template <typename T, typename ... FArgs>
+    T a_T(FArgs&&... args) {
+        gTypeName = demangle_it(typeid(&A<Args...>::a_T<T, FArgs...>).name(), 
"A::a_T-2");
+        return T{};
+    }
+
+    template <typename ... FArgs>
+    static void sa(FArgs&&... args) {
+        gTypeName = demangle_it(typeid(A<Args...>).name(), "A::sa-1");
+        gTypeName += "::";
+        gTypeName += demangle_it(typeid(A<Args...>::sa<FArgs...>).name(), 
"A::sa-2");
+    }
+
+    template <typename T, typename ... FArgs>
+    static T sa_T(FArgs&&... args) {
+        gTypeName = demangle_it(typeid(A<Args...>).name(), "A::sa_T-1");
+        gTypeName +=  "::";
+        gTypeName += demangle_it(typeid(A<Args...>::sa_T<T, FArgs...>).name(), 
"A::sa_T-2");
+        return T{};
+    }
+};
+
+class B {
+public:
+    B() {
+        gTypeName = demangle_it(typeid(B).name(), "B::B");
+    }
+    B(const B&) = default;
+    B(B&&) = default;
+    B& operator=(const B&) = default;
+    B& operator=(B&&) = default;
+
+    template <typename ... FArgs>
+    void b(FArgs&&... args) {
+        gTypeName = demangle_it(typeid(&B::b<FArgs...>).name(), "B::b-2");
+    }
+
+    template <typename T, typename ... FArgs>
+    T b_T(FArgs&&... args) {
+        gTypeName = demangle_it(typeid(&B::b_T<T, FArgs...>).name(), 
"B::b_T-2");
+        return T{};
+    }
+
+    template <typename ... FArgs>
+    static void sb(FArgs&&... args) {
+        gTypeName = demangle_it(typeid(B).name(), "B::sb-1");
+        gTypeName += "::";
+        gTypeName +=  demangle_it(typeid(B::sb<FArgs...>).name(), "B::sb-2");
+    }
+
+    template <typename T, typename ... FArgs>
+    static T sb_T(FArgs&&... args) {
+        gTypeName = demangle_it(typeid(B).name(), "B::sb_T-1");
+        gTypeName += "::";
+        gTypeName += demangle_it(typeid(B::sb_T<T, FArgs...>).name(), 
"B::sb_T-2");
+        return T{};
+    }
+};
+
+template <typename ... Args>
+void fn(Args&&... args) {
+    gTypeName = demangle_it(typeid(fn<Args...>).name(), "fn");
+}
+
+template <typename T, typename ... Args>
+T fn_T(Args&&... args) {
+    gTypeName = demangle_it(typeid(fn<Args...>).name(), "fn_T");
+    return T{};
+}
+
+} // namespace some_variadic
+
+
+//===========================================================================
+// template with empty body
+namespace T_WithEmptyBody {
+
+#ifdef WIN32
+extern __declspec(dllimport) std::string side_effect;
+#else
+extern std::string side_effect;
+#endif
+
+template<typename T>
+void some_empty();
+
+} // namespace T_WithEmptyBody
+
+
+//===========================================================================
+// template with catch-all (void*, void**)overloads
+namespace T_WithGreedyOverloads {
+
+class SomeClass {
+    double fD;
+};
+
+class WithGreedy1 {
+public:
+    template<class T>
+    int get_size(T*) { return (int)sizeof(T); }
+    int get_size(void*, bool force=false) { return -1; }
+};
+
+class WithGreedy2 {
+public:
+    template<class T>
+    int get_size(T*) { return (int)sizeof(T); }
+    int get_size(void**, bool force=false) { return -1; }
+};
+
+class DoesNotExist;
+
+class WithGreedy3 {
+public:
+    template<class T>
+    int get_size(T*) { return (int)sizeof(T); }
+    int get_size(DoesNotExist*, bool force=false) { return -1; }
+};
+
+} // namespace T_WithGreedyOverloads
+
+
+//===========================================================================
+// template with overloaded non-templated and templated setitem
+namespace TemplateWithSetItem {
+
+template <typename T>
+class MyVec {
+private:
+   std::vector<T> fData;
+
+public:
+   using size_type = typename std::vector<T>::size_type;
+
+   MyVec(size_type count) : fData(count) {}
+
+   T & operator[](size_type index) { return fData[index]; }
+
+   // The definition of this templated operator causes the issue
+   template <typename V>
+   MyVec operator[](const MyVec<V> &conds) const { return MyVec(2); }
+};
+
+} // namespace TemplateWithSetItem
+
+#endif // !CPPYY_TEST_TEMPLATES_H
diff --git a/pypy/module/_cppyy/test/templates.xml 
b/pypy/module/_cppyy/test/templates.xml
--- a/pypy/module/_cppyy/test/templates.xml
+++ b/pypy/module/_cppyy/test/templates.xml
@@ -16,4 +16,21 @@
   <function name="SomeNS::some_bar" />
   <function name="SomeNS::tuplify" />
 
+  <class name="TemplatedCallable" />
+
+  <namespace name="TemplateHiding" />
+  <class pattern="TemplateHiding::*" />
+
+  <namespace name="using_problem" />
+
+  <namespace name="some_variadic" />
+  <class pattern="some_variadic::*" />
+  <function pattern="some_variadic::*" />
+  <variable pattern="some_variadic::*" />
+
+  <namespace name="T_WithEmptyBody" />
+
+  <namespace name="T_WithGreedyOverloads" />
+  <class pattern="T_WithGreedyOverloads::*" />
+
 </lcgdict>
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to