Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
March 30, 2014 Template magic exercise | ||||
---|---|---|---|---|
| ||||
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. |
March 30, 2014 Re: Template magic exercise | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jack Applegame | Sorry. Not "getter", should be "elementsAccessor" instead. |
March 30, 2014 Re: Template magic exercise | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jack Applegame | 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. */ } --- |
March 30, 2014 Re: Template magic exercise | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | Wraper structure again. Is there solution without it? |
March 30, 2014 Re: Template magic exercise | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jack Applegame | 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 |
March 31, 2014 Re: Template magic exercise | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jack Applegame | 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.
|
Copyright © 1999-2021 by the D Language Foundation