mirror of https://github.com/swig/swig
233 lines
6.3 KiB
OpenEdge ABL
233 lines
6.3 KiB
OpenEdge ABL
%module friends_nested
|
||
|
||
// Issue #2845 - handling friends in nested classes
|
||
|
||
#pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS
|
||
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) CPP17::AA::BB::more_acc_cond::squeezed_in;
|
||
|
||
%rename(operatorshift) operator<<;
|
||
%rename(operatorshift) *::operator<<;
|
||
|
||
%feature("flatnested") spot::acc_cond::mark_t;
|
||
|
||
%inline %{
|
||
#include <iostream>
|
||
|
||
std::ostream& std_cout_reference() {
|
||
return std::cout;
|
||
}
|
||
|
||
// Stops cout from outputting anything
|
||
void std_cout_badbit() {
|
||
std_cout_reference().setstate(std::ios_base::badbit);
|
||
}
|
||
|
||
namespace spot
|
||
{
|
||
class option_map
|
||
{
|
||
public:
|
||
friend std::ostream& operator<<(std::ostream& os, const option_map& m); // 1
|
||
};
|
||
|
||
class acc_cond
|
||
{
|
||
public:
|
||
struct mark_t
|
||
{
|
||
mark_t operator<<(unsigned i) const; // 2
|
||
friend std::ostream& operator<<(std::ostream& os, mark_t m); // 3
|
||
};
|
||
};
|
||
|
||
std::ostream& operator<<(std::ostream& os, const acc_cond& acc); // 4
|
||
}
|
||
|
||
void test_from_cplusplus() {
|
||
spot::option_map om;
|
||
{
|
||
using namespace spot;
|
||
operator<<(std::cout, om);
|
||
}
|
||
|
||
spot::acc_cond::mark_t m;
|
||
m.operator<<(999);
|
||
{
|
||
using namespace spot;
|
||
operator<<(std::cout, m);
|
||
}
|
||
|
||
spot::acc_cond a;
|
||
operator<<(std::cout, a);
|
||
}
|
||
%}
|
||
|
||
%{
|
||
namespace spot {
|
||
std::ostream& operator<<(std::ostream& os, const option_map& m) { os << "operator<< 1" << std::endl; return os; } // 1
|
||
acc_cond::mark_t acc_cond::mark_t::operator<<(unsigned i) const { std::ostream& os = std_cout_reference(); os << "operator<< 2" << std::endl; return spot::acc_cond::mark_t(); } // 2
|
||
std::ostream& operator<<(std::ostream& os, acc_cond::mark_t m) { os << "operator<< 3" << std::endl; return os; } // 3
|
||
std::ostream& operator<<(std::ostream& os, const acc_cond& acc) { os << "operator<< 4" << std::endl; return os; } // 4
|
||
}
|
||
%}
|
||
|
||
%{
|
||
// Compiler using traditional (non-C++17 nested) namespaces
|
||
namespace CPP17 {
|
||
namespace AA {
|
||
namespace BB {
|
||
class more_acc_cond {
|
||
public:
|
||
struct squeezed_in {
|
||
struct more_mark_t
|
||
{
|
||
more_mark_t operator<<(unsigned i) const; // 6
|
||
friend std::ostream& operator<<(std::ostream& os, const more_mark_t& m); // 5
|
||
};
|
||
};
|
||
};
|
||
}
|
||
}
|
||
}
|
||
%}
|
||
|
||
// SWIG testing C++17 nested namespaces
|
||
namespace CPP17::AA::BB {
|
||
class more_acc_cond {
|
||
public:
|
||
struct squeezed_in {
|
||
struct more_mark_t
|
||
{
|
||
more_mark_t operator<<(unsigned i) const; // 6
|
||
friend std::ostream& operator<<(std::ostream& os, const more_mark_t& m); // 5
|
||
};
|
||
};
|
||
};
|
||
}
|
||
|
||
%{
|
||
namespace CPP17 {
|
||
namespace AA {
|
||
namespace BB {
|
||
more_acc_cond::squeezed_in::more_mark_t more_acc_cond::squeezed_in::more_mark_t::operator<<(unsigned i) const { std::ostream& os = std_cout_reference(); os << "operator<< 6" << std::endl; return more_acc_cond::squeezed_in::more_mark_t(); }
|
||
std::ostream& operator<<(std::ostream& os, const more_acc_cond::squeezed_in::more_mark_t& m) { os << "operator<< 5" << std::endl; return os; } // 5
|
||
}
|
||
}
|
||
}
|
||
%}
|
||
|
||
|
||
%inline %{
|
||
#if defined(SWIG)
|
||
#define STATIC_FOR_ANONYMOUS
|
||
#else
|
||
// For gcc in C++98 mode (at least) to avoid:
|
||
// error: unnamed type with no linkage used to declare variable ‘<unnamed class> instance’ with linkage
|
||
#define STATIC_FOR_ANONYMOUS static
|
||
#endif
|
||
struct BaseForAnon {
|
||
virtual ~BaseForAnon() {}
|
||
};
|
||
|
||
// Unnamed nested classes are ignored but were causing code that did not compile
|
||
STATIC_FOR_ANONYMOUS class /*unnamed*/ : public BaseForAnon {
|
||
int member_var;
|
||
public:
|
||
friend int myfriend();
|
||
|
||
// nested unnamed class
|
||
class /*unnamed*/ {
|
||
int inner_member_var;
|
||
public:
|
||
// below caused SWIG crash
|
||
friend int innerfriend();
|
||
} anon_inner;
|
||
|
||
} instance;
|
||
|
||
// friend members ignored too as the entire unnamed class is ignored!
|
||
int myfriend() {
|
||
return instance.member_var;
|
||
}
|
||
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 instantiation within the class
|
||
%template(InnerDouble) InnerTemplate<double>;
|
||
%template(InnerShort) InnerTemplate<short>;
|
||
#endif
|
||
};
|
||
}
|
||
}
|
||
%}
|
||
|
||
%extend OuterSpace::InnerSpace::OuterClass {
|
||
// Template instantiation 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
|