mirror of https://github.com/swig/swig
Further fixes for handling friends in deeply nested mixes of templates and classes
The appropriate namespace for friends declared in a class/template were not always being correctly determined when %template is used in nested hierarchies. Further improvements to previous commit.
This commit is contained in:
parent
4564a60915
commit
e511df0026
|
@ -145,3 +145,80 @@ int innerfriend() {
|
|||
return instance.anon_inner.inner_member_var;
|
||||
}
|
||||
%}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Test nested templates and classes
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
// %feature("flatnested"); // This ought to work for languages that don't support nested structs, but InnerInnerStruct is multiply defined at the time of writing
|
||||
#if defined(SWIGJAVA) || defined(SWIGCSHARP)
|
||||
|
||||
%inline %{
|
||||
namespace OuterSpace {
|
||||
namespace InnerSpace {
|
||||
struct OuterClass {
|
||||
template<typename T> struct InnerTemplate {
|
||||
InnerTemplate(T i) : val(i) {}
|
||||
void InstanceMethod(T i) {}
|
||||
static void StaticMethod(T i) {}
|
||||
friend T friendly(InnerTemplate/*<T>*/ t) {return t.val; }
|
||||
T thung(InnerTemplate/*<T>*/ t) {return t.val; }
|
||||
|
||||
struct InnerInnerStruct {
|
||||
InnerInnerStruct(T p) : priv(p) {}
|
||||
friend T friendly_inner_qualified(const InnerTemplate<T>::InnerInnerStruct& i) { return i.priv; }
|
||||
// friend T friendly_inner(const InnerInnerStruct& i) { return i.priv; } // TODO: without template parameters
|
||||
void dosomething(const InnerInnerStruct& x) {}
|
||||
void useinner(const InnerTemplate& x) {}
|
||||
private:
|
||||
T priv;
|
||||
};
|
||||
|
||||
void use_inner_inner(InnerInnerStruct iis) {}
|
||||
|
||||
template<typename X> struct InnerInnerTemplate {
|
||||
InnerInnerTemplate(T t, X x) : t_private(t), x_private(x) {}
|
||||
friend X friendly_inner_x(const InnerTemplate<T>::InnerInnerTemplate<X>& i) { return i.x_private; }
|
||||
friend T friendly_inner_t(const InnerTemplate<T>::InnerInnerTemplate<X>& i) { return i.t_private; }
|
||||
void doanything(const InnerInnerTemplate& x) {}
|
||||
void useT(const T& ttt) {}
|
||||
void useX(const X& xxx) {}
|
||||
struct VeryInner {
|
||||
VeryInner(const T& t, const X& x) {}
|
||||
friend X very_inner(const InnerTemplate<T>::InnerInnerTemplate<X>::VeryInner& vi) { return 0; }
|
||||
};
|
||||
private:
|
||||
T t_private;
|
||||
X x_private;
|
||||
};
|
||||
|
||||
private:
|
||||
T val;
|
||||
};
|
||||
#if defined(SWIG)
|
||||
// Template instantation within the class
|
||||
%template(InnerDouble) InnerTemplate<double>;
|
||||
%template(InnerShort) InnerTemplate<short>;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
}
|
||||
%}
|
||||
|
||||
%extend OuterSpace::InnerSpace::OuterClass {
|
||||
// Template instantation after the class is fully defined and added to the symbol tables
|
||||
%template(InnerInt) InnerTemplate<int>;
|
||||
}
|
||||
|
||||
|
||||
%extend OuterSpace::InnerSpace::OuterClass::InnerTemplate<double> {
|
||||
%template(InnerInnerBool) InnerInnerTemplate<bool>;
|
||||
}
|
||||
%extend OuterSpace::InnerSpace::OuterClass::InnerTemplate<int> {
|
||||
%template(InnerInnerChar) InnerInnerTemplate<char>;
|
||||
}
|
||||
%extend OuterSpace::InnerSpace::OuterClass::InnerTemplate<short> {
|
||||
%template(InnerInnerString) InnerInnerTemplate<char *>;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,5 +25,41 @@ public class friends_nested_runme {
|
|||
friends_nested.operatorshift(cout, m);
|
||||
friends_nested.operatorshift(cout, ac);
|
||||
friends_nested.operatorshift(cout, mm);
|
||||
|
||||
|
||||
// Test nested templates and classes
|
||||
OuterClass oc = new OuterClass();
|
||||
OuterClass.InnerDouble inner_double = new OuterClass.InnerDouble(1.1);
|
||||
OuterClass.InnerInt inner_int = new OuterClass.InnerInt(2);
|
||||
OuterClass.InnerShort inner_short = new OuterClass.InnerShort((short)3);
|
||||
|
||||
friends_nested.friendly(inner_double);
|
||||
friends_nested.friendly(inner_int);
|
||||
friends_nested.friendly(inner_short);
|
||||
|
||||
OuterClass.InnerDouble.InnerInnerStruct iis_double = new OuterClass.InnerDouble.InnerInnerStruct(11.1);
|
||||
OuterClass.InnerInt.InnerInnerStruct iis_int = new OuterClass.InnerInt.InnerInnerStruct(22);
|
||||
OuterClass.InnerShort.InnerInnerStruct iis_short = new OuterClass.InnerShort.InnerInnerStruct((short)33);
|
||||
|
||||
friends_nested.friendly_inner_qualified(iis_double);
|
||||
friends_nested.friendly_inner_qualified(iis_int);
|
||||
friends_nested.friendly_inner_qualified(iis_short);
|
||||
|
||||
OuterClass.InnerDouble.InnerInnerBool iit_bool = new OuterClass.InnerDouble.InnerInnerBool(111.1, true);
|
||||
OuterClass.InnerInt.InnerInnerChar iit_char = new OuterClass.InnerInt.InnerInnerChar(222, 'x');
|
||||
OuterClass.InnerShort.InnerInnerString iit_string = new OuterClass.InnerShort.InnerInnerString((short)333, "hi");
|
||||
|
||||
friends_nested.friendly_inner_x(iit_bool);
|
||||
friends_nested.friendly_inner_x(iit_char);
|
||||
friends_nested.friendly_inner_x(iit_string);
|
||||
|
||||
OuterClass.InnerDouble.InnerInnerBool.VeryInner vi_iit_bool = new OuterClass.InnerDouble.InnerInnerBool.VeryInner(111.1, true);
|
||||
OuterClass.InnerInt.InnerInnerChar.VeryInner vi_iit_char = new OuterClass.InnerInt.InnerInnerChar.VeryInner(222, 'x');
|
||||
OuterClass.InnerShort.InnerInnerString.VeryInner vi_iit_string = new OuterClass.InnerShort.InnerInnerString.VeryInner((short)333, "hi");
|
||||
|
||||
friends_nested.very_inner(vi_iit_bool);
|
||||
friends_nested.very_inner(vi_iit_char);
|
||||
friends_nested.very_inner(vi_iit_string);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -430,6 +430,7 @@ static void add_symbols(Node *n) {
|
|||
/* Friends methods in a class are declared in the namespace enclosing the class (outer most class if a nested class) */
|
||||
String *prefix = name ? Swig_scopename_prefix(name) : 0;
|
||||
Node *outer = currentOuterClass;
|
||||
Symtab *namespace_symtab;
|
||||
old_prefix = Namespaceprefix;
|
||||
old_scope = Swig_symbol_current();
|
||||
|
||||
|
@ -437,7 +438,10 @@ static void add_symbols(Node *n) {
|
|||
while (Getattr(outer, "nested:outer")) {
|
||||
outer = Getattr(outer, "nested:outer");
|
||||
}
|
||||
Swig_symbol_setscope(Getattr(outer, "prev_symtab"));
|
||||
namespace_symtab = Getattr(outer, "sym:symtab");
|
||||
if (!namespace_symtab)
|
||||
namespace_symtab = Getattr(outer, "prev_symtab");
|
||||
Swig_symbol_setscope(namespace_symtab);
|
||||
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
|
||||
|
||||
if (!prefix) {
|
||||
|
@ -742,7 +746,7 @@ static void add_symbols_copy(Node *n) {
|
|||
}
|
||||
add_only_one = 0;
|
||||
if (Equal(nodeType(n), "class")) {
|
||||
Setattr(n, "prev_symtab", Swig_symbol_current());
|
||||
/* add_symbols() above sets "sym:symtab", so "prev_symtab" is not required */
|
||||
old_inclass = inclass;
|
||||
oldCurrentOuterClass = currentOuterClass;
|
||||
inclass = 1;
|
||||
|
|
Loading…
Reference in New Issue