August 31, 2013 Re: Any trick for defining an operator overload in a different namespace? | ||||
---|---|---|---|---|
| ||||
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 |
Copyright © 1999-2021 by the D Language Foundation