Add support for friend templates, including operator overloading.

Closes #196.
This commit is contained in:
William S Fulton 2015-05-04 10:01:34 +01:00
commit 428b6176df
10 changed files with 146 additions and 3 deletions

View file

@ -234,6 +234,7 @@ CPP_TEST_CASES += \
features \
fragments \
friends \
friends_template \
funcptr_cpp \
fvirtual \
global_namespace \

View file

@ -0,0 +1,26 @@
%module cpp_template_friend
template<typename T> T template_friend1(T);
template<typename T> T template_friend1(T);
struct MyTemplate1 {
template<typename T> friend T template_friend1(T);
};
template<typename T> T template_friend2(T);
struct MyTemplate2 {
template<typename T> friend T template_friend2(T);
};
template<typename T> T template_friend2(T);
int normal_friend1(int);
int normal_friend1(int);
struct MyClass1 {
friend int normal_friend1(int);
};
int normal_friend2(int);
struct MyClass2 {
friend int normal_friend2(int);
};
int normal_friend2(int);

View file

@ -0,0 +1,8 @@
cpp_template_friend.i:4: Warning 302: Identifier 'template_friend1' redefined (ignored),
cpp_template_friend.i:3: Warning 302: previous definition of 'template_friend1'.
cpp_template_friend.i:13: Warning 302: Identifier 'template_friend2' redefined (ignored),
cpp_template_friend.i:9: Warning 302: previous definition of 'template_friend2'.
cpp_template_friend.i:17: Warning 322: Redundant redeclaration of 'normal_friend1',
cpp_template_friend.i:16: Warning 322: previous declaration of 'normal_friend1'.
cpp_template_friend.i:26: Warning 322: Redundant redeclaration of 'normal_friend2',
cpp_template_friend.i:22: Warning 322: previous declaration of 'normal_friend2'.

View file

@ -0,0 +1,46 @@
%module friends_template
%{
template <typename Type> class MyClass;
template <typename Type> int operator<<(double un, const MyClass <Type> & x) { return 0; }
template <typename Type> int funk_hidden(double is, MyClass <Type> & x) { return 2; }
template <typename T> T template_friend_hidden(T t) { return t + 1; }
%}
%inline %{
template <typename Type> int operator>>(double is, MyClass <Type> & x) { return 1; }
template <typename Type> int funk_seen(double is, MyClass <Type> & x) { return 2; }
template <typename T> T template_friend_seen(T t1, T t2) { return t1 + t2; }
int friend_plain_seen(int i) { return i; }
template <class Type> class MyClass
{
friend int operator<< <Type>(double un, const MyClass <Type> & x);
friend int operator>> <Type>(double is, MyClass <Type> & x);
friend int funk_hidden <Type>(double is, MyClass <Type> & x);
friend int funk_seen <Type>(double is, MyClass <Type> & x);
};
struct MyTemplate {
template <typename T> friend T template_friend_hidden(T);
template <typename T> friend T template_friend_seen(T, T);
friend int friend_plain_seen(int i);
};
MyClass<int> makeMyClassInt() { return MyClass<int>(); }
%}
// Although the friends in MyClass are automatically instantiated via %template(MyClassDouble) MyClass<int>,
// the operator friends are not valid and hence %rename is needed.
%rename(OperatorInputDouble) operator>> <double>;
%rename(OperatorOutputDouble) operator<< <double>;
%template(MyClassDouble) MyClass<double>;
%template(TemplateFriendHiddenInt) template_friend_hidden<int>;
%template(TemplateFriendSeenInt) template_friend_seen<int>;
// These have no %template(XX) MyClass<int> to instantiate, but they can be instantiated separately...
%template(OperatorInputInt) operator>> <int>;
%template(OperatorFunkSeenInt) funk_seen <int>;

View file

@ -0,0 +1,28 @@
import friends_template.*;
public class friends_template_runme {
static {
try {
System.loadLibrary("friends_template");
} 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[]) {
friends_template.OperatorOutputDouble(1.1, new MyClassDouble());
friends_template.OperatorInputDouble(1.1, new MyClassDouble());
friends_template.funk_hidden(1.1, new MyClassDouble());
friends_template.funk_seen(1.1, new MyClassDouble());
friends_template.TemplateFriendHiddenInt(0);
friends_template.TemplateFriendSeenInt(0, 0);
SWIGTYPE_p_MyClassT_int_t myClassInt = friends_template.makeMyClassInt();
friends_template.OperatorInputInt(1, myClassInt);
friends_template.OperatorFunkSeenInt(1.1, myClassInt);
}
}