Thread overview
Template magic exercise
Mar 30, 2014
Jack Applegame
Mar 30, 2014
Jack Applegame
Mar 30, 2014
anonymous
Mar 30, 2014
Jack Applegame
Mar 30, 2014
Artur Skawina
Mar 31, 2014
Frustrated
March 30, 2014
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
Sorry. Not "getter", should be "elementsAccessor" instead.
March 30, 2014
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
Wraper structure again. Is there solution without it?
March 30, 2014
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
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.