Any trick for defining an operator overload in a different namespace?
Artur Skawina
art.08.09 at gmail.com
Sat Aug 31 06:26:26 PDT 2013
On 08/31/13 12:07, Andrej Mitrovic wrote:
> But this explicitly stores the 'this' reference in the struct, I was
> wondering if anyone knows of a trick to avoid having to do that. As
> you can tell I just want a more convenient operator-based syntax over
> calling the 'assign' method, but I don't want the operator to live in
> the class space itself (because then I'd have to use "this[...] =
> that", which is a little quirky for my taste).
Not sure this qualifies as a "trick", but it does what you're asking
for and can be extended further.
struct A {
mixin Namespace!("x", "x_");
int x_min = 42;
int x_max(int a) { return a/2; }
int x_sum(int a, int b) { return a+b; }
@property int x_prop() { return 23; }
@property int x_prop(int a) { return a*a; }
@property int setmin(int a) { return x_min = a; }
mixin Namespace!("opts", "opts_");
void opts_opIndexAssign(T)(T value, string option) {
if (option=="min")
x_min = value;
}
}
class C {
mixin Namespace!("x", "x_");
int x_min = 42;
int x_max(int a) { return a/2; }
int x_sum(int a, int b) { return a+b; }
@property int x_prop() { return 23; }
@property int x_prop(int a) { return a*a; }
mixin Namespace!("opts", "opts_");
void opts_opIndexAssign(T)(T value, string option) {
if (option=="min")
x_min = value;
}
}
import std.stdio;
int main() {
A a;
//C a = new C; // Works too.
writeln(a.x.min);
a.x.min = 17;
writeln(a.x.min);
writeln(a.x.max(4));
writeln(a.x.sum(4, 3));
writeln(a.x.prop);
writeln(a.x.prop=42);
a.x.min = 13;
writeln(a.x.min);
a.opts["min"] = 1234;
writeln(a.x.min);
const A ca;
writeln(ca.x.min);
writeln(typeof({return ca.x.min;}()).stringof);
// ca.x.min = 13; // Disallowed.
return 0;
}
struct NS(O, string PF) {
O _realobjref;
template opDispatch(string M) {
enum _EVALSTR = "this.tupleof[0]."~PF~M;
@property auto ref opDispatch()()
if (is(typeof(function { auto _ = mixin(_EVALSTR); }))) {
return mixin(_EVALSTR);
}
@property auto ref opDispatch(A)(A a)
if (is(typeof(function { return mixin(_EVALSTR~"=a"); }))) {
return mixin(_EVALSTR~"=a");
}
auto ref opDispatch(A...)(A a)
if (is(typeof(function { return mixin(_EVALSTR~"(a)"); }))) {
return mixin(_EVALSTR~"(a)");
}
}
auto ref opIndexAssign(A...)(auto ref A a) { // XXX Won't work if there are ref&non-ref overloads.
return mixin("this.tupleof[0]."~PF~"opIndexAssign(a)");
}
}
mixin template Namespace(string N, string P) {
mixin(q{
template }~N~q{(this THIS) }~"{"~q{
@property }~N~q{() const @trusted }~"{"~q{
static if (is(THIS==struct)) return NS!(THIS*, }~P.stringof~q{)(cast(THIS*)&this);
else static if (is(THIS==class)) return NS!(THIS, }~P.stringof~q{)(cast(THIS)this);
else static assert (0);
}~"}\n"~
"}"
);
}
artur
More information about the Digitalmars-d-learn
mailing list