Enhance %extend to extend a class with template methods

This commit is contained in:
William S Fulton 2017-01-22 10:29:34 +00:00
commit b538070016
7 changed files with 207 additions and 1 deletions

View file

@ -7,6 +7,19 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 3.0.12 (in progress) Version 3.0.12 (in progress)
============================ ============================
2017-01-22: wsfulton
Issue #876 Enhance %extend to extend a class with template methods, eg:
struct Foo {
%extend {
template<typename T>
void do_stuff(int a, T b) {
...
}
}
};
%template(do_stuff_inst) Foo::do_stuff<double>;
2017-01-22: kwwette 2017-01-22: kwwette
[Octave] add support for version 4.2 [Octave] add support for version 4.2
- The Octave API now uses some C++11 features. It is recommended to use - The Octave API now uses some C++11 features. It is recommended to use

View file

@ -3635,6 +3635,43 @@ This will generate two overloaded wrapper methods, the first will take a single
and the second will take two integer arguments. and the second will take two integer arguments.
</p> </p>
<p>
It is even possible to extend a class via <tt>%extend</tt> with template methods, for example:
</p>
<div class="code">
<pre>
%include &lt;std_string.i&gt;
%inline %{
class ExtendMe {
public:
template &lt;typename T&gt;
T do_stuff_impl(int a, T b, double d) {
return b;
}
};
%}
%extend ExtendMe {
template&lt;typename T&gt;
T do_overloaded_stuff(T b) {
return $self-&gt;do_stuff_impl(0, b, 4.0);
}
}
%template(do_overloaded_stuff) ExtendMe::do_overloaded_stuff&lt;std::string&gt;;
%template(do_overloaded_stuff) ExtendMe::do_overloaded_stuff&lt;double&gt;;
</pre>
</div>
<p>
The wrapped <tt>ExtendMe</tt> class will then have two (overloaded) methods called <tt>do_overloaded_stuff</tt>.
</p>
<p>
<b>Compatibility Note</b>: Extending a class with template methods was added in version 3.0.12
</p>
<p> <p>
Needless to say, SWIG's template support provides plenty of opportunities to Needless to say, SWIG's template support provides plenty of opportunities to
break the universe. That said, an important final point is that <b>SWIG does break the universe. That said, an important final point is that <b>SWIG does

View file

@ -227,6 +227,7 @@ CPP_TEST_CASES += \
extend_placement \ extend_placement \
extend_special_variables \ extend_special_variables \
extend_template \ extend_template \
extend_template_method \
extend_template_ns \ extend_template_ns \
extend_typedef_class \ extend_typedef_class \
extern_c \ extern_c \

View file

@ -0,0 +1,62 @@
%module extend_template_method
%include <std_string.i>
%inline %{
class ExtendMe {
public:
template <typename T>
T do_stuff_impl(int a, T b, double d) {
return b;
}
};
%}
%extend ExtendMe {
template<typename T>
T do_stuff(int a, T b) {
return $self->do_stuff_impl(a, b, 4.0);
}
template<typename T>
T do_overloaded_stuff(T b) {
return $self->do_stuff_impl(0, b, 4.0);
}
}
%template(do_stuff_double) ExtendMe::do_stuff<double>;
%template(do_stuff_string) ExtendMe::do_stuff<std::string>;
%template(do_overloaded_stuff) ExtendMe::do_overloaded_stuff<std::string>;
%template(do_overloaded_stuff) ExtendMe::do_overloaded_stuff<double>;
%inline %{
template<typename X>
class TemplateExtendMe {
public:
template <typename T>
T template_stuff_impl(X a, T b, double d) {
return b;
}
};
%}
%extend TemplateExtendMe {
template<typename T>
T do_template_stuff(int a, T b) {
return $self->template_stuff_impl(a, b, 4.0);
}
template<typename T>
T do_template_overloaded_stuff(T b) {
return $self->template_stuff_impl(0, b, 4.0);
}
%template(do_template_stuff_double) do_template_stuff<double>;
%template(do_template_stuff_string) do_template_stuff<std::string>;
%template(do_template_overloaded_stuff) do_template_overloaded_stuff<std::string>;
%template(do_template_overloaded_stuff) do_template_overloaded_stuff<double>;
}
%template(TemplateExtend) TemplateExtendMe<int>;

View file

@ -0,0 +1,57 @@
import extend_template_method.*;
public class extend_template_method_runme {
static {
try {
System.loadLibrary("extend_template_method");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) {
{
ExtendMe em = new ExtendMe();
{
double ret_double = em.do_stuff_double(1, 1.1);
if (ret_double != 1.1)
throw new RuntimeException("double failed " + ret_double);
String ret_string = em.do_stuff_string(1, "hello there");
if (!ret_string.equals("hello there"))
throw new RuntimeException("string failed " + ret_string);
}
{
double ret_double = em.do_overloaded_stuff(1.1);
if (ret_double != 1.1)
throw new RuntimeException("double failed " + ret_double);
String ret_string = em.do_overloaded_stuff("hello there");
if (!ret_string.equals("hello there"))
throw new RuntimeException("string failed " + ret_string);
}
}
{
TemplateExtend em = new TemplateExtend();
{
double ret_double = em.do_template_stuff_double(1, 1.1);
if (ret_double != 1.1)
throw new RuntimeException("double failed " + ret_double);
String ret_string = em.do_template_stuff_string(1, "hello there");
if (!ret_string.equals("hello there"))
throw new RuntimeException("string failed " + ret_string);
}
{
double ret_double = em.do_template_overloaded_stuff(1.1);
if (ret_double != 1.1)
throw new RuntimeException("double failed " + ret_double);
String ret_string = em.do_template_overloaded_stuff("hello there");
if (!ret_string.equals("hello there"))
throw new RuntimeException("string failed " + ret_string);
}
}
}
}

View file

@ -0,0 +1,36 @@
from extend_template_method import *
em = ExtendMe()
ret_double = em.do_stuff_double(1, 1.1)
if ret_double != 1.1:
raise RuntimeError("double failed " + ret_double)
ret_string = em.do_stuff_string(1, "hello there")
if ret_string != "hello there":
raise RuntimeError("string failed " + ret_string)
ret_double = em.do_overloaded_stuff(1.1)
if ret_double != 1.1:
raise RuntimeError("double failed " + ret_double)
ret_string = em.do_overloaded_stuff("hello there")
if ret_string != "hello there":
raise RuntimeError("string failed " + ret_string)
em = TemplateExtend()
ret_double = em.do_template_stuff_double(1, 1.1)
if ret_double != 1.1:
raise RuntimeError("double failed " + ret_double)
ret_string = em.do_template_stuff_string(1, "hello there")
if ret_string != "hello there":
raise RuntimeError("string failed " + ret_string)
ret_double = em.do_template_overloaded_stuff(1.1)
if ret_double != 1.1:
raise RuntimeError("double failed " + ret_double)
ret_string = em.do_template_overloaded_stuff("hello there")
if ret_string != "hello there":
raise RuntimeError("string failed " + ret_string)

View file

@ -1267,7 +1267,7 @@ int Language::memberfunctionHandler(Node *n) {
if (GetFlag(n, "explicitcall")) if (GetFlag(n, "explicitcall"))
DirectorExtraCall = CWRAP_DIRECTOR_ONE_CALL; DirectorExtraCall = CWRAP_DIRECTOR_ONE_CALL;
Swig_MethodToFunction(n, NSpace, ClassType, Getattr(n, "template") ? SmartPointer : Extend | SmartPointer | DirectorExtraCall, director_type, Swig_MethodToFunction(n, NSpace, ClassType, Getattr(n, "template") ? Extend | SmartPointer : Extend | SmartPointer | DirectorExtraCall, director_type,
is_member_director(CurrentClass, n)); is_member_director(CurrentClass, n));
Setattr(n, "sym:name", fname); Setattr(n, "sym:name", fname);