Commit 9162cdcd authored by wlav's avatar wlav
Browse files

prepare for more template tests

--HG--
branch : cppyy-dev
parent 65d87222eef1
......@@ -981,8 +981,8 @@ W_CPPTemplateOverload.typedef = TypeDef(
)
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 @@ class W_CPPTemplateStaticOverload(W_CPPStaticOverload, TemplateOverloadMixin):
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 @@ class W_CPPTemplateStaticOverload(W_CPPStaticOverload, TemplateOverloadMixin):
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 @@ class W_CPPScopeDecl(W_Root):
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']
......
......@@ -10,3 +10,28 @@ long MyTemplatedMethodClass::get_long_size() { return (long)42; /* "lying" */
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
#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 @@ private:
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 @@ struct SomeResult {
};
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 @@ struct DerivedClassUsingStatic : public BaseClassWithStatic<T> {
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
......@@ -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>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment