From: Josh C. <jc...@nc...> - 2008-04-03 21:32:11
|
On Thu, 3 Apr 2008, Jason Stewart wrote: > I was thinking that we would only auto-generate the code for '=' if > the class being wrapped contained a mutator. That we wouldn't need '=' > to be defined if only '-' or '+' were defined by the class... Assuming "fallback" is set appropriately. With the current setting it will synthesize, e.g., '++' and '+=' if + is defined. I don't think it does much harm to have '=' when it's unnecessary. >> In many cases that's true. If I do >> >> $b = $a; >> $a += 1; >> >> Perl makes a copy ($b and $a are no longer the same, which is one of the >> things that makes me nervous). > > I'm not understanding why that makes you nervous. Is it because of the > auto-magic operations happening behind the scenes? A couple of reasons. One is that it's different from how methods work: calling a method on $a that changes it does not make $a no longer equal to $b. In fact I currently map operator++ to Incr(), which will not destroy equality, whereas calling overloaded '++' in Perl will destroy equality. I worry that users will be quite confused (I don't mean just because of the change in my wrappers). It gets even uglier, though, when we involve C++ objects, which don't hold Perl references to objects that they contain or refer to. Suppose a class contains an instance of another class that has overloaded operator++. The containing class provides access to this instance via a method that returns a C++ reference. Does the member instance get incremented, or not, in the following cases?: 1) $foo = $bar->GetFoo(); ++$foo; 2) $foo = $bar->GetFoo(); $foo2 = $foo; ++$foo; 3) $foo = $bar->GetFoo(); $foo++; Empirical answer: in the first case, yes; in the second case, no; in the third case, yes when run as a script, no when run in the debugger (using the '=' I mention below). Even a simple rule like "pre-increment changes the original object unless there's assignment" could lead to confusion and programming errors. I'm not sure it's that simple. Some other unfortunate things: A C++ class may have mutators but no public copy constructor. We can't wrap the mutators properly then. We have no way of calling C++ pre-increment for pre-increment and C++ post-increment for post-increment, or having just one when C++ provides just one. In practice, Perl will make post-increment for us from C++ pre-increment. >> Clearly we don't want $a or $b to change >> class. But suppose that a base class CBase defines opeperator++ and a derived >> class CDer does not override it. ++der returns a CBase in C++. OK, that's a >> bad C++ design, but if Perl calls CBase's Perl-defined "=" in the course of >> handling it, should it make a CBase or a CDer? > > The Perl way would to have the copy constructor defined in CBase and > return an instance of the derived class. The perl implementation looks > like: > > Package CBase; > sub __copy__ { > my $obj = shift; > my $class = ref($obj); > my $new_obj = CBase_copy($obj); > return bless $new_obj, $class; > } > > I do that in SWIG with by defining a DYNAMIC_CAST for the classes with > subclasses. I was envisioning simply adding "=" => sub { my $cl = ref($_[0]); new $cl($_[0]) }, to the 'use overload', which seems to work. Do these accomplish the same thing (I don't know what CBase_copy does)? Josh |