Perl module now fully supports operator overloading
added script for testing overloading support which uses Perl test harness: Test::More updated HTML docs for operators git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@8246 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
466eeaa532
commit
18771f8267
4 changed files with 282 additions and 52 deletions
|
|
@ -1228,36 +1228,29 @@ Please refer to the "SWIG Basics" chapter for more information.
|
|||
|
||||
<H3><a name="Perl5_nn23"></a>26.4.9 Operators</H3>
|
||||
|
||||
<p>
|
||||
As of version 1.3.27 SWIG automatically renames the most common C++ operators, and maps them into the perl module with the proper 'use overload ...' so you don't need to do any work.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
C++ operators can also be wrapped using the <tt>%rename</tt> directive. All you need to do is
|
||||
give the operator the name of a valid Perl identifier. For example:
|
||||
</p>
|
||||
<p>
|
||||
The following C++ operators are currently supported by the Perl module:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%rename(add_complex) operator+(Complex &, Complex &);
|
||||
...
|
||||
Complex operator+(Complex &, Complex &);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Now, in Perl, you can do this:
|
||||
</p>
|
||||
|
||||
<div class="targetlang">
|
||||
<pre>
|
||||
use example;
|
||||
$a = example::new_Complex(2,3);
|
||||
$b = example::new_Complex(4,-1);
|
||||
$c = example::add_complex($a,$b);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Some preliminary work on mapping C++ operators into Perl operators has been completed. This is covered later.
|
||||
</p>
|
||||
<ul>
|
||||
<li>operator++ </li>
|
||||
<li>operator-- </li>
|
||||
<li>operator+ </li>
|
||||
<li>operator- </li>
|
||||
<li>operator* </li>
|
||||
<li>operator/ </li>
|
||||
<li>operator== </li>
|
||||
<li>operator!= </li>
|
||||
<li>operator% </li>
|
||||
<li>operator> </li>
|
||||
<li>operator< </li>
|
||||
<li>operator and </li>
|
||||
<li>operator or </li>
|
||||
</ul>
|
||||
|
||||
<H3><a name="Perl5_nn24"></a>26.4.10 Modules and packages</H3>
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ see bottom for a set of possible tests
|
|||
%warnfilter(362,389,383,384);
|
||||
#endif
|
||||
|
||||
#if !defined(SWIGLUA)
|
||||
#if !defined(SWIGLUA) || !defined(SWIGPERL)
|
||||
%rename(Equal) operator =;
|
||||
%rename(PlusEqual) operator +=;
|
||||
%rename(MinusEqual) operator -=;
|
||||
|
|
@ -60,6 +60,7 @@ see bottom for a set of possible tests
|
|||
class Op{
|
||||
public:
|
||||
int i;
|
||||
int j;
|
||||
Op(int a=0):i(a)
|
||||
{}
|
||||
Op(const Op& o):i(o.i)
|
||||
|
|
@ -88,6 +89,8 @@ public:
|
|||
|
||||
|
||||
// unary operators
|
||||
Op operator++() {i++; return *this;}
|
||||
Op operator--() {i--; return *this;}
|
||||
Op operator-() const {return Op(-i);}
|
||||
bool operator !() const {return !(i);}
|
||||
|
||||
|
|
@ -105,6 +108,9 @@ public:
|
|||
int operator()(int a=0){return i+a;}
|
||||
int operator()(int a,int b){return i+a+b;}
|
||||
|
||||
<<<<<<< operator_overload.i
|
||||
// TODO: <<,<<=
|
||||
=======
|
||||
// increment/decrement operators
|
||||
Op& operator++(){++i; return *this;} // prefix ++
|
||||
Op& operator++(int){i++; return *this;} // postfix ++
|
||||
|
|
@ -112,6 +118,7 @@ public:
|
|||
Op& operator--(int){i--; return *this;} // postfix --
|
||||
|
||||
// TODO: <<,<<=
|
||||
>>>>>>> 1.6
|
||||
};
|
||||
|
||||
// just to complicate matters
|
||||
|
|
@ -129,6 +136,9 @@ inline bool operator>=(const Op& a,const Op& b){return a.i>=b.i;}
|
|||
// we need to extend the class
|
||||
// to make the friends & non members part of the class
|
||||
%extend Op{
|
||||
Op operator and(const Op& b){return Op(self->i&&b.i);}
|
||||
Op operator or(const Op& b){return Op(self->i||b.i);}
|
||||
|
||||
Op operator+(const Op& b){return Op(self->i+b.i);}
|
||||
Op operator-(const Op& b){return Op(self->i-b.i);}
|
||||
Op operator*(const Op& b){return Op(self->i*b.i);}
|
||||
|
|
|
|||
137
Examples/test-suite/perl5/operator_overload_runme.pl
Normal file
137
Examples/test-suite/perl5/operator_overload_runme.pl
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
#!/usr/bin/perl -w
|
||||
use strict;
|
||||
use Test::More tests => 24;
|
||||
use operator_overload;
|
||||
|
||||
pass("loaded");
|
||||
|
||||
my $op = operator_overload::Op->new();
|
||||
|
||||
isa_ok($op, "operator_overload::Op");
|
||||
|
||||
my $op2 = operator_overload::Op->new();
|
||||
|
||||
isa_ok($op2, "operator_overload::Op");
|
||||
|
||||
# operator equal
|
||||
$op->{i} = 5;
|
||||
$op2->{i} = 3;
|
||||
|
||||
ok(not ($op == $op2), "operator equal: not equal");
|
||||
|
||||
$op->{i} = 3;
|
||||
ok(($op == $op2), "operator equal: equal");
|
||||
|
||||
# operator equal
|
||||
$op->{i} = 5;
|
||||
$op2->{i} = 3;
|
||||
|
||||
ok(($op != $op2), "operator not equal: not equal");
|
||||
|
||||
$op->{i} = 3;
|
||||
ok(not ($op != $op2), "operator not equal: equal");
|
||||
|
||||
# stringify operator
|
||||
$op->{i} = 3;
|
||||
is("Op(3)", "$op", "operator stringify");
|
||||
|
||||
# addition operator
|
||||
$op->{i} = 3;
|
||||
$op2->{i} = 3;
|
||||
my $op3 = $op + $op2;
|
||||
is($op3->{i}, 6, "operator addition");
|
||||
|
||||
# addition assignment operator
|
||||
$op->{i} = 3;
|
||||
$op2->{i} = 3;
|
||||
$op += $op2;
|
||||
is($op->{i}, 6, "operator additive assignment");
|
||||
|
||||
# subtraction operator
|
||||
$op3->{i} = 6;
|
||||
$op2->{i} = 3;
|
||||
$op = $op3 - $op2;
|
||||
is($op->{i}, 3, "operator subtration");
|
||||
|
||||
# subtractive assignment operator
|
||||
$op->{i} = 6;
|
||||
$op2->{i} = 3;
|
||||
$op -= $op2;
|
||||
is($op->{i}, 3, "operator subtrative assignment");
|
||||
|
||||
# multiplication operator
|
||||
$op->{i} = 3;
|
||||
$op2->{i} = 3;
|
||||
$op3 = $op * $op2;
|
||||
is($op3->{i}, 9, "operator multiplication");
|
||||
|
||||
# division operator
|
||||
$op->{i} = 9;
|
||||
$op2->{i} = 3;
|
||||
$op3 = $op / $op2;
|
||||
is($op3->{i}, 3, "operator division");
|
||||
|
||||
# modulus operator
|
||||
$op->{i} = 8;
|
||||
$op2->{i} = 3;
|
||||
$op3 = $op % $op2;
|
||||
is($op3->{i}, 2, "operator modulus");
|
||||
|
||||
# greater than operator
|
||||
$op->{i} = 8;
|
||||
$op2->{i} = 3;
|
||||
ok($op > $op2, "operator greater than");
|
||||
ok(not ($op2 > $op), "operator greater than");
|
||||
$op->{i} = 3;
|
||||
ok(not ($op2 > $op), "operator greater than");
|
||||
ok(not ($op > $op2), "operator greater than");
|
||||
|
||||
# lesser than operator
|
||||
$op2->{i} = 8;
|
||||
$op->{i} = 3;
|
||||
ok($op < $op2, "operator lesser than");
|
||||
ok(not ($op2 < $op), "operator lesser than");
|
||||
$op2->{i} = 3;
|
||||
ok(not ($op2 < $op), "operator lesser than");
|
||||
ok(not ($op < $op2), "operator lesser than");
|
||||
|
||||
TODO : {
|
||||
local $TODO = "I can't get Perl to trigger overloaded 'and' and 'or'";
|
||||
|
||||
# operator and
|
||||
$op->{i} = 0;
|
||||
$op2->{i} = 1;
|
||||
ok(not ($op && $op2), "operator and");
|
||||
$op->{i} = 0;
|
||||
$op2->{i} = 0;
|
||||
ok(not ($op && $op2), "operator and");
|
||||
$op->{i} = 1;
|
||||
$op2->{i} = 1;
|
||||
ok(($op && $op2), "operator and");
|
||||
|
||||
# operator or
|
||||
$op->{i} = 0;
|
||||
$op2->{i} = 1;
|
||||
ok(($op || $op2), "operator or");
|
||||
$op->{i} = 1;
|
||||
ok(($op || $op2), "operator or");
|
||||
$op->{i} = 0;
|
||||
$op2->{i} = 0;
|
||||
ok(not ($op || $op2), "operator or");
|
||||
};
|
||||
|
||||
# increment operator
|
||||
$op->{i} = 7;
|
||||
$op++;
|
||||
is($op->{i}, 8, "operator increment");
|
||||
|
||||
# decrement operator
|
||||
$op->{i} = 7;
|
||||
$op--;
|
||||
is($op->{i}, 6, "operator decrement");
|
||||
|
||||
# inverse operator
|
||||
$op->{i} = 3;
|
||||
$op2 = -$op;
|
||||
is($op2->{i}, -3, "operator inverse");
|
||||
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
* Loic Dachary (loic@ceic.com)
|
||||
* David Fletcher
|
||||
* Gary Holt
|
||||
* Jason Stewart (jason@openinformatics.com)
|
||||
* Jason Stewart (jasons@apache.org)
|
||||
*
|
||||
* Copyright (C) 1999-2000. The University of Chicago
|
||||
* See the file LICENSE for information on usage and redistribution.
|
||||
|
|
@ -726,7 +726,7 @@ public:
|
|||
"XSRETURN(argvi);\n",
|
||||
"fail:\n",
|
||||
cleanup,
|
||||
"croak(\"swig/perl error\");\n"
|
||||
"croak(Nullch);\n"
|
||||
"XSRETURN(0);\n"
|
||||
"}\n",
|
||||
"}\n",
|
||||
|
|
@ -1177,20 +1177,53 @@ public:
|
|||
for (ki = First(operators); ki.key; ki = Next(ki)) {
|
||||
char *name = Char(ki.key);
|
||||
// fprintf(stderr,"found name: <%s>\n", name);
|
||||
if (strstr(name, "operator_equal_to")) {
|
||||
Printv(pm, tab4, "\"==\" => sub { $_[0]->operator_equal_to($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "operator_not_equal_to")) {
|
||||
Printv(pm, tab4, "\"!=\" => sub { $_[0]->operator_not_equal_to($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "operator_assignment")) {
|
||||
Printv(pm, tab4, "\"=\" => sub { $_[0]->operator_assignment($_[1])},\n",NIL);
|
||||
if (strstr(name, "__eq__")) {
|
||||
Printv(pm, tab4, "\"==\" => sub { $_[0]->__eq__($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "__ne__")) {
|
||||
Printv(pm, tab4, "\"!=\" => sub { $_[0]->__ne__($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "__assign__")) {
|
||||
Printv(pm, tab4, "\"=\" => sub { $_[0]->__assign__($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "__str__")) {
|
||||
Printv(pm, tab4, "'\"\"' => sub { $_[0]->__str__()},\n",NIL);
|
||||
} else if (strstr(name, "__plusplus__")) {
|
||||
Printv(pm, tab4, "\"++\" => sub { $_[0]->__plusplus__()},\n",NIL);
|
||||
} else if (strstr(name, "__minmin__")) {
|
||||
Printv(pm, tab4, "\"--\" => sub { $_[0]->__minmin__()},\n",NIL);
|
||||
} else if (strstr(name, "__add__")) {
|
||||
Printv(pm, tab4, "\"+\" => sub { $_[0]->__add__($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "__sub__")) {
|
||||
Printv(pm, tab4, "\"-\" => sub { $_[0]->__sub__($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "__mul__")) {
|
||||
Printv(pm, tab4, "\"*\" => sub { $_[0]->__mul__($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "__div__")) {
|
||||
Printv(pm, tab4, "\"/\" => sub { $_[0]->__div__($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "__mod__")) {
|
||||
Printv(pm, tab4, "\"%\" => sub { $_[0]->__mod__($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "__and__")) {
|
||||
Printv(pm, tab4, "\"&&\" => sub { $_[0]->__and__($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "__or__")) {
|
||||
Printv(pm, tab4, "\"||\" => sub { $_[0]->__or__($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "__gt__")) {
|
||||
Printv(pm, tab4, "\">\" => sub { $_[0]->__gt__($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "__lt__")) {
|
||||
Printv(pm, tab4, "\"<\" => sub { $_[0]->__lt__($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "__pluseq__")) {
|
||||
Printv(pm, tab4, "\"+=\" => sub { $_[0]->__pluseq__($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "__mineq__")) {
|
||||
Printv(pm, tab4, "\"-=\" => sub { $_[0]->__mineq__($_[1])},\n",NIL);
|
||||
} else if (strstr(name, "__neg__")) {
|
||||
Printv(pm, tab4, "\"neg\" => sub { $_[0]->__neg__()},\n",NIL);
|
||||
} else {
|
||||
fprintf(stderr,"Unknown operator: %s\n", name);
|
||||
}
|
||||
}
|
||||
Printv(pm, tab4, "\"fallback\" => 1;\n",NIL);
|
||||
}
|
||||
/* If we are inheriting from a base class, set that up */
|
||||
|
||||
// make use strict happy
|
||||
Printv(pm, "use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);\n", NIL);
|
||||
|
||||
/* If we are inheriting from a base class, set that up */
|
||||
|
||||
Printv(pm, "@ISA = qw(", NIL);
|
||||
|
||||
|
|
@ -1262,20 +1295,77 @@ public:
|
|||
|
||||
if ((blessed) && (!Getattr(n,"sym:nextSibling"))) {
|
||||
|
||||
if (Strstr(symname, "operator") == symname) {
|
||||
if (Strstr(symname, "operator_equal_to")) {
|
||||
DohSetInt(operators,"operator_equal_to",1);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "operator_not_equal_to")) {
|
||||
DohSetInt(operators,"operator_not_equal_to",1);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "operator_assignment")) {
|
||||
DohSetInt(operators,"operator_assignment",1);
|
||||
have_operators = 1;
|
||||
} else {
|
||||
Printf(stderr,"Unknown operator: %s\n", symname);
|
||||
}
|
||||
// fprintf(stderr,"Found member_func operator: %s\n", symname);
|
||||
if (Strstr(symname, "__eq__")) {
|
||||
DohSetInt(operators,"__eq__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__ne__")) {
|
||||
DohSetInt(operators,"__ne__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__assign__")) {
|
||||
DohSetInt(operators,"__assign__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__str__")) {
|
||||
DohSetInt(operators,"__str__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
} else if (Strstr(symname, "__add__")) {
|
||||
DohSetInt(operators,"__add__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__sub__")) {
|
||||
DohSetInt(operators,"__sub__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__mul__")) {
|
||||
DohSetInt(operators,"__mul__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__div__")) {
|
||||
DohSetInt(operators,"__div__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__mod__")) {
|
||||
DohSetInt(operators,"__mod__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__and__")) {
|
||||
DohSetInt(operators,"__and__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__or__")) {
|
||||
DohSetInt(operators,"__or__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__gt__")) {
|
||||
DohSetInt(operators,"__gt__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__lt__")) {
|
||||
DohSetInt(operators,"__lt__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__neg__")) {
|
||||
DohSetInt(operators,"__neg__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__plusplus__")) {
|
||||
DohSetInt(operators,"__plusplus__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__minmin__")) {
|
||||
DohSetInt(operators,"__minmin__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__mineq__")) {
|
||||
DohSetInt(operators,"__mineq__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
} else if (Strstr(symname, "__pluseq__")) {
|
||||
DohSetInt(operators,"__pluseq__",1);
|
||||
Printf(stderr,"Found member_func operator: %s\n", symname);
|
||||
have_operators = 1;
|
||||
}
|
||||
|
||||
if (Getattr(n,"feature:shadow")) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue