[D] Operator overloading support for D1 and D2.
As mentioned in the documentation, opIndexAssign and implicit casting are not supported yet. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12357 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
9a0f7ed06c
commit
38c88a0931
7 changed files with 425 additions and 75 deletions
|
|
@ -58,7 +58,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
%define SWIGD_CLASS_BODIES(OP_EQUALS_RETURN)
|
||||
|
||||
// Unfortunately, the »package« visibility attribute does not work in D when the
|
||||
// module in question is in the root package (happens if no -package is specified
|
||||
// at the SWIG command line), so we are stuck with public visibility for
|
||||
|
|
@ -72,18 +72,14 @@ public this(void* cObject, bool ownCObject) {
|
|||
swigCMemOwn = ownCObject;
|
||||
}
|
||||
|
||||
public override OP_EQUALS_RETURN opEquals(Object rhs) {
|
||||
if (auto other = cast($dclassname)rhs) {
|
||||
return (swigCPtr == other.swigCPtr);
|
||||
}
|
||||
return super.opEquals(rhs);
|
||||
}
|
||||
|
||||
public static void* swigGetCPtr($dclassname obj) {
|
||||
return (obj is null) ? null : obj.swigCPtr;
|
||||
}
|
||||
|
||||
mixin $imdmodule.SwigOperatorDefinitions;
|
||||
%}
|
||||
|
||||
|
||||
%typemap(dbody_derived) SWIGTYPE %{
|
||||
private void* swigCPtr;
|
||||
|
||||
|
|
@ -92,16 +88,11 @@ public this(void* cObject, bool ownCObject) {
|
|||
swigCPtr = cObject;
|
||||
}
|
||||
|
||||
public override OP_EQUALS_RETURN opEquals(Object rhs) {
|
||||
if (auto other = cast($dclassname)rhs) {
|
||||
return (swigCPtr == other.swigCPtr);
|
||||
}
|
||||
return super.opEquals(rhs);
|
||||
}
|
||||
|
||||
public static void* swigGetCPtr($dclassname obj) {
|
||||
return (obj is null) ? null : obj.swigCPtr;
|
||||
}
|
||||
|
||||
mixin $imdmodule.SwigOperatorDefinitions;
|
||||
%}
|
||||
|
||||
|
||||
|
|
@ -120,16 +111,11 @@ protected this() {
|
|||
swigCPtr = null;
|
||||
}
|
||||
|
||||
public override OP_EQUALS_RETURN opEquals(Object rhs) {
|
||||
if (auto other = cast($dclassname)rhs) {
|
||||
return (swigCPtr == other.swigCPtr);
|
||||
}
|
||||
return super.opEquals(rhs);
|
||||
}
|
||||
|
||||
public static void* swigGetCPtr($dclassname obj) {
|
||||
return (obj is null) ? null : obj.swigCPtr;
|
||||
}
|
||||
|
||||
mixin $imdmodule.SwigOperatorDefinitions;
|
||||
%}
|
||||
|
||||
|
||||
|
|
@ -138,35 +124,19 @@ public static void* swigGetCPtr($dclassname obj) {
|
|||
*/
|
||||
|
||||
%typemap(dbody) SWIGTYPE (CLASS::*) %{
|
||||
private char* m_swigCMemberPtr;
|
||||
private char* swigCPtr;
|
||||
|
||||
public this(char* cMemberPtr, bool futureUse) {
|
||||
m_swigCMemberPtr = cMemberPtr;
|
||||
swigCPtr = cMemberPtr;
|
||||
}
|
||||
|
||||
protected this() {
|
||||
m_swigCMemberPtr = null;
|
||||
swigCPtr = null;
|
||||
}
|
||||
|
||||
public override OP_EQUALS_RETURN opEquals(Object rhs) {
|
||||
if (auto other = cast($dclassname)rhs) {
|
||||
return (m_swigCMemberPtr == other.m_swigCMemberPtr);
|
||||
}
|
||||
return super.opEquals(rhs);
|
||||
}
|
||||
|
||||
|
||||
package static char* swigGetCMemberPtr($dclassname obj) {
|
||||
return (obj is null) ? null : obj.m_swigCMemberPtr;
|
||||
return (obj is null) ? null : obj.swigCPtr;
|
||||
}
|
||||
|
||||
mixin $imdmodule.SwigOperatorDefinitions;
|
||||
%}
|
||||
%enddef
|
||||
|
||||
|
||||
#if SWIG_D_VERSION == 1
|
||||
SWIGD_CLASS_BODIES(int)
|
||||
#else
|
||||
SWIGD_CLASS_BODIES(bool)
|
||||
#endif
|
||||
|
||||
#undef SWIGD_CLASS_BODIES
|
||||
|
|
|
|||
|
|
@ -4,15 +4,36 @@
|
|||
* Mapping of C++ operator overloading methods to D.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#if (SWIG_D_VERSION == 1)
|
||||
|
||||
%rename(opAdd) *::operator+;
|
||||
%pragma(d) imdmodulecode=%{
|
||||
template SwigOperatorDefinitions() {
|
||||
public override int opEquals(Object o) {
|
||||
if (auto rhs = cast(typeof(this))o) {
|
||||
if (swigCPtr == rhs.swigCPtr) return 1;
|
||||
static if (is(typeof(swigOpEquals(rhs)))) {
|
||||
return swigOpEquals(rhs) ? 1 : 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return super.opEquals(o);
|
||||
}
|
||||
%}
|
||||
// opEquals is emitted in pure C mode as well to define two proxy classes
|
||||
// pointing to the same struct as equal.
|
||||
|
||||
#ifdef __cplusplus
|
||||
%rename(opPos) *::operator+();
|
||||
%rename(opPos) *::operator+() const;
|
||||
%rename(opNeg) *::operator-();
|
||||
%rename(opNeg) *::operator-() const;
|
||||
%rename(opCom) *::operator~();
|
||||
%rename(opCom) *::operator~() const;
|
||||
|
||||
%rename(opAdd) *::operator+;
|
||||
%rename(opAddAssign) *::operator+=;
|
||||
%rename(opSub) *::operator-;
|
||||
%rename(opNeg) *::operator-();
|
||||
%rename(opSubAssign) *::operator-=;
|
||||
%rename(opMul) *::operator*;
|
||||
%rename(opMulAssign) *::operator*=;
|
||||
|
|
@ -20,8 +41,6 @@
|
|||
%rename(opDivAssign) *::operator/=;
|
||||
%rename(opMod) *::operator%;
|
||||
%rename(opModAssign) *::operator%=;
|
||||
|
||||
%rename(opCom) *::operator~();
|
||||
%rename(opAnd) *::operator&;
|
||||
%rename(opAndAssign) *::operator&=;
|
||||
%rename(opOr) *::operator|;
|
||||
|
|
@ -34,44 +53,207 @@
|
|||
%rename(opShrAssign) *::operator>>=;
|
||||
|
||||
%rename(opIndex) *::operator[](unsigned) const;
|
||||
%rename(opIndexAssign) *::operator[](unsigned);
|
||||
%rename(opCall) *::operator();
|
||||
// opIndexAssign is not currently generated, it needs more extensive support
|
||||
// mechanisms.
|
||||
|
||||
%rename(opCall) *::operator();
|
||||
|
||||
// !a is not overrideable in D1.
|
||||
%ignoreoperator(LNOT) operator!;
|
||||
|
||||
// a != b is rewritten as !a.opEquals(b) in D.
|
||||
// For now, just ignore both of them, since there would be quite a bit of magic
|
||||
// needed to correctly generate a wrapper method for non-primitives types (there is
|
||||
// only one opEquals overload with an Object parameter in D).
|
||||
%ignoreoperator(EQ) operator==;
|
||||
%ignoreoperator(NOTEQUAL) operator!=;
|
||||
|
||||
// opCmp is used in D.
|
||||
%ignoreoperator(LT) operator<;
|
||||
%ignoreoperator(LTEQUAL) operator<=;
|
||||
%ignoreoperator(GT) operator>;
|
||||
%ignoreoperator(GTEQUAL) operator>=;
|
||||
%rename(swigOpEquals) *::operator==;
|
||||
%rename(swigOpLt) *::operator<;
|
||||
%rename(swigOpLtEquals) *::operator<=;
|
||||
%rename(swigOpGt) *::operator>;
|
||||
%rename(swigOpGtEquals) *::operator>=;
|
||||
|
||||
// a != b is rewritten as !a.opEquals(b) in D.
|
||||
%ignoreoperator(NOTEQUAL) operator!=;
|
||||
|
||||
// The logic operators are not overrideable in D.
|
||||
%ignoreoperator(LAND) operator&&;
|
||||
%ignoreoperator(LOR) operator||;
|
||||
|
||||
// ++/--a is rewritten as a +/-= 1 in D.
|
||||
%ignoreoperator(PLUSPLUS) operator++();
|
||||
%ignoreoperator(MINUSMINUS) operator--();
|
||||
%ignoreoperator(PLUSPLUS) operator++(int);
|
||||
%ignoreoperator(MINUSMINUS) operator--(int);
|
||||
// ++/--a is rewritten as a +/-= 1 in D1,so ignore the prefix operators.
|
||||
%ignoreoperator(PLUSPLUS) *::operator++();
|
||||
%ignoreoperator(MINUSMINUS) *::operator--();
|
||||
%rename(swigOpInc) *::operator++(int);
|
||||
%rename(swigOpDec) *::operator--(int);
|
||||
|
||||
// The C++ assignment operator does not translate well to D where custom types
|
||||
// have reference semantics.
|
||||
// The C++ assignment operator does not translate well to D where the proxy
|
||||
// classes have reference semantics.
|
||||
%ignoreoperator(EQ) operator=;
|
||||
|
||||
%pragma(d) imdmodulecode=%{
|
||||
public override int opCmp(Object o) {
|
||||
static if (is(typeof(swigOpLt(typeof(this).init) &&
|
||||
swigOpEquals(typeof(this).init)))) {
|
||||
if (auto rhs = cast(typeof(this))o) {
|
||||
if (swigOpLt(rhs)) {
|
||||
return -1;
|
||||
} else if (swigOpEquals(rhs)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.opCmp(o);
|
||||
}
|
||||
|
||||
public typeof(this) opPostInc(T = int)(T unused = 0) {
|
||||
static assert(
|
||||
is(typeof(swigOpInc(int.init))),
|
||||
"opPostInc called on " ~ typeof(this).stringof ~ ", but no postfix " ~
|
||||
"increment operator exists in the corresponding C++ class."
|
||||
);
|
||||
return swigOpInc(int.init);
|
||||
}
|
||||
|
||||
public typeof(this) opPostDec(T = int)(T unused = 0) {
|
||||
static assert(
|
||||
is(typeof(swigOpDec(int.init))),
|
||||
"opPostInc called on " ~ typeof(this).stringof ~ ", but no postfix " ~
|
||||
"decrement operator exists in the corresponding C++ class."
|
||||
);
|
||||
return swigOpDec(int.init);
|
||||
}
|
||||
%}
|
||||
#endif
|
||||
|
||||
%pragma(d) imdmodulecode=%{
|
||||
}
|
||||
%}
|
||||
|
||||
#else
|
||||
%pragma(d) imdmodulecode=%{
|
||||
mixin template SwigOperatorDefinitions() {
|
||||
public override bool opEquals(Object o) {
|
||||
if (auto rhs = cast(typeof(this))o) {
|
||||
if (swigCPtr == rhs.swigCPtr) return true;
|
||||
static if (is(typeof(swigOpEquals(rhs)))) {
|
||||
return swigOpEquals(rhs);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return super.opEquals(o);
|
||||
}
|
||||
%}
|
||||
// opEquals is emitted in pure C mode as well to define two proxy classes
|
||||
// pointing to the same struct as equal.
|
||||
|
||||
// Operator overloading works completely different in D2, proper support will
|
||||
// probably need fairly extensive code generation support.
|
||||
#ifdef __cplusplus
|
||||
%rename(swigOpPos) *::operator+();
|
||||
%rename(swigOpPos) *::operator+() const;
|
||||
%rename(swigOpNeg) *::operator-();
|
||||
%rename(swigOpNeg) *::operator-() const;
|
||||
%rename(swigOpCom) *::operator~();
|
||||
%rename(swigOpCom) *::operator~() const;
|
||||
%rename(swigOpInc) *::operator++();
|
||||
%rename(swigOpDec) *::operator--();
|
||||
%ignoreoperator(PLUSPLUS) *::operator++(int);
|
||||
%ignoreoperator(MINUSMINUS) *::operator--(int);
|
||||
// The postfix increment/decrement operators are ignored because they are
|
||||
// rewritten to (auto t = e, ++e, t) in D2. The unary * operator (used for
|
||||
// pointer dereferencing in C/C++) isn't mapped to opUnary("*") by default,
|
||||
// despite this would be possible in D2 – the difference in member access
|
||||
// semantics would only lead to confusion in most cases.
|
||||
|
||||
%rename(swigOpAdd) *::operator+;
|
||||
%rename(swigOpSub) *::operator-;
|
||||
%rename(swigOpMul) *::operator*;
|
||||
%rename(swigOpDiv) *::operator/;
|
||||
%rename(swigOpMod) *::operator%;
|
||||
%rename(swigOpAnd) *::operator&;
|
||||
%rename(swigOpOr) *::operator|;
|
||||
%rename(swigOpXor) *::operator^;
|
||||
%rename(swigOpShl) *::operator<<;
|
||||
%rename(swigOpShr) *::operator>>;
|
||||
|
||||
%rename(swigOpAddAssign) *::operator+=;
|
||||
%rename(swigOpSubAssign) *::operator-=;
|
||||
%rename(swigOpMulAssign) *::operator*=;
|
||||
%rename(swigOpDivAssign) *::operator/=;
|
||||
%rename(swigOpModAssign) *::operator%=;
|
||||
%rename(swigOpAndAssign) *::operator&=;
|
||||
%rename(swigOpOrAssign) *::operator|=;
|
||||
%rename(swigOpXorAssign) *::operator^=;
|
||||
%rename(swigOpShlAssign) *::operator<<=;
|
||||
%rename(swigOpShrAssign) *::operator>>=;
|
||||
|
||||
%rename(opIndex) *::operator[];
|
||||
// opIndexAssign is not currently generated, it needs more extensive support
|
||||
// mechanisms.
|
||||
|
||||
%rename(opCall) *::operator();
|
||||
|
||||
%rename(swigOpEquals) *::operator==;
|
||||
%rename(swigOpLt) *::operator<;
|
||||
%rename(swigOpLtEquals) *::operator<=;
|
||||
%rename(swigOpGt) *::operator>;
|
||||
%rename(swigOpGtEquals) *::operator>=;
|
||||
|
||||
// a != b is rewritten as !a.opEquals(b) in D.
|
||||
%ignoreoperator(NOTEQUAL) operator!=;
|
||||
|
||||
// The logic operators are not overrideable in D.
|
||||
%ignoreoperator(LAND) operator&&;
|
||||
%ignoreoperator(LOR) operator||;
|
||||
|
||||
// The C++ assignment operator does not translate well to D where the proxy
|
||||
// classes have reference semantics.
|
||||
%ignoreoperator(EQ) operator=;
|
||||
|
||||
%pragma(d) imdmodulecode=%{
|
||||
public override int opCmp(Object o) {
|
||||
static if (__traits(compiles, swigOpLt(typeof(this).init) &&
|
||||
swigOpEquals(typeof(this).init))) {
|
||||
if (auto rhs = cast(typeof(this))o) {
|
||||
if (swigOpLt(rhs)) {
|
||||
return -1;
|
||||
} else if (swigOpEquals(rhs)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.opCmp(o);
|
||||
}
|
||||
|
||||
private template swigOpBinary(string operator, string name) {
|
||||
enum swigOpBinary = `public void opOpAssign(string op, T)(T rhs) if (op == "` ~ operator ~
|
||||
`" && __traits(compiles, swigOp` ~ name ~ `Assign(rhs))) { swigOp` ~ name ~ `Assign(rhs);}` ~
|
||||
`public auto opBinary(string op, T)(T rhs) if (op == "` ~ operator ~
|
||||
`" && __traits(compiles, swigOp` ~ name ~ `(rhs))) { return swigOp` ~ name ~ `(rhs);}`;
|
||||
}
|
||||
mixin(swigOpBinary!("+", "Add"));
|
||||
mixin(swigOpBinary!("-", "Sub"));
|
||||
mixin(swigOpBinary!("*", "Mul"));
|
||||
mixin(swigOpBinary!("/", "Div"));
|
||||
mixin(swigOpBinary!("%", "Mod"));
|
||||
mixin(swigOpBinary!("&", "And"));
|
||||
mixin(swigOpBinary!("|", "Or"));
|
||||
mixin(swigOpBinary!("^", "Xor"));
|
||||
mixin(swigOpBinary!("<<", "Shl"));
|
||||
mixin(swigOpBinary!(">>", "Shr"));
|
||||
|
||||
private template swigOpUnary(string operator, string name) {
|
||||
enum swigOpUnary = `public auto opUnary(string op)() if (op == "` ~ operator ~
|
||||
`" && __traits(compiles, swigOp` ~ name ~ `())) { return swigOp` ~ name ~ `();}`;
|
||||
}
|
||||
mixin(swigOpUnary!("+", "Pos"));
|
||||
mixin(swigOpUnary!("-", "Neg"));
|
||||
mixin(swigOpUnary!("~", "Com"));
|
||||
mixin(swigOpUnary!("++", "Inc"));
|
||||
mixin(swigOpUnary!("--", "Dec"));
|
||||
%}
|
||||
#endif
|
||||
|
||||
%pragma(d) imdmodulecode=%{
|
||||
}
|
||||
%}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue