www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template magic exercise

reply "Jack Applegame" <japplegame gmail.com> writes:
Target is to create a template for mapping member "array 
accessor" to member function.

For example:

class Foo {
   ...
   int elementsAccessor(size_t index) { ... }
   ...
   mixin MagicTemplateMixin!("elements", elementsAccessor);
   // or better
   alias elements = SuperMagicTemplate!elementsAccessor;
}

and now we can call Foo.getter like this:

auto foo = new Foo;
int el = foo.elements[10]; // int el = foo.getter(10);

I wrote poor and ugly solution with proxy structure:
http://dpaste.dzfl.pl/93085910f8c7
I hate it. :)

I need more powerful spell, but my magic level is too low.
Mar 30 2014
next sibling parent "Jack Applegame" <japplegame gmail.com> writes:
Sorry. Not "getter", should be "elementsAccessor" instead.
Mar 30 2014
prev sibling next sibling parent reply "anonymous" <anonymous example.com> writes:
On Sunday, 30 March 2014 at 12:42:16 UTC, Jack Applegame wrote:
 Target is to create a template for mapping member "array 
 accessor" to member function.

 For example:

 class Foo {
   ...
   int elementsAccessor(size_t index) { ... }
   ...
   mixin MagicTemplateMixin!("elements", elementsAccessor);
   // or better
   alias elements = SuperMagicTemplate!elementsAccessor;
 }

 and now we can call Foo.getter like this:

 auto foo = new Foo;
 int el = foo.elements[10]; // int el = foo.getter(10);

 I wrote poor and ugly solution with proxy structure:
 http://dpaste.dzfl.pl/93085910f8c7
 I hate it. :)

 I need more powerful spell, but my magic level is too low.
Maybe less is more here: --- struct OpIndexFromAccessor(R, PS) { R delegate(PS) dg; R opIndex(PS ps) { return dg(ps); } } auto opIndexFromAccessor(R, PS)(R delegate(PS) accessor) { return OpIndexFromAccessor!(R, PS)(accessor); } class Foo { int elementsAccessor(size_t index) { ... } auto elements() {return opIndexFromAccessor(&elementsAccessor);} /* This is hardly more complex than the mixin or alias variants. */ } ---
Mar 30 2014
parent reply "Jack Applegame" <japplegame gmail.com> writes:
Wraper structure again. Is there solution without it?
Mar 30 2014
parent Artur Skawina <art.08.09 gmail.com> writes:
On 03/30/14 15:36, Jack Applegame wrote:
 Wraper structure again. Is there solution without it?
No. D only allows op overloading in structs/unions/classes, so one of those will be necessary. The simpliest solution would be something like: class C { int elementsAccessor(size_t index) { ... } property ref elements() { struct Elements(O) { auto opIndex(size_t i) { auto o = *cast(O*)&this; return o.elementsAccessor(i); } disable this(this); } return *cast(Elements!(typeof(this))*)&this; } } and if you need that code to be safe: auto opIndex(size_t i) safe { auto o = (f) trusted { return *cast(O*)f; }(&this); return o.elementsAccessor(i); } // etc artur
Mar 30 2014
prev sibling parent "Frustrated" <Who where.com> writes:
On Sunday, 30 March 2014 at 12:42:16 UTC, Jack Applegame wrote:
 Target is to create a template for mapping member "array 
 accessor" to member function.

 For example:

 class Foo {
   ...
   int elementsAccessor(size_t index) { ... }
   ...
   mixin MagicTemplateMixin!("elements", elementsAccessor);
   // or better
   alias elements = SuperMagicTemplate!elementsAccessor;
 }

 and now we can call Foo.getter like this:

 auto foo = new Foo;
 int el = foo.elements[10]; // int el = foo.getter(10);

 I wrote poor and ugly solution with proxy structure:
 http://dpaste.dzfl.pl/93085910f8c7
 I hate it. :)

 I need more powerful spell, but my magic level is too low.
While this doesn't work maybe you can put in a request to add the functionality: import std.stdio, std.cstream; import std.variant; import std.conv; class Foo { Variant[] opDispatchIndex(string name, E...)(E elements) { writeln(name); return null; } } void main() { auto f = new Foo; f.elements[3]; // Works if opDispatchIndex existed din.getc(); } alternatively, if you don't mind the extra bloat: import std.stdio, std.cstream; import std.variant; import std.conv; struct opIndexStruct { void opIndex(in size_t i) { writeln("op - ", i); } } class Foo { property opIndexStruct elements() { opIndexStruct o; return o; } } void main() { auto f = new Foo; f.elements[3]; din.getc(); } this works because elements is a property and we don't have to call with parenthesis. e.g., f.elements()[3]. Hence f.elements works. [3] is acted on by the return value of elements(), which is a struct that supports opIndex(one could alternative use alias this to wrap the struct in a type that supports indexing. As is the code isn't very useful but should provide you with the ability to achieve what you want.
Mar 30 2014