Thread overview
Container templates
Feb 19, 2014
Frustrated
Feb 19, 2014
Meta
Feb 19, 2014
Frustrated
Feb 19, 2014
monarch_dodra
Feb 19, 2014
Meta
Feb 20, 2014
Frustrated
Feb 22, 2014
Meta
February 19, 2014
Are there container templates that one can mixin to classes that
give them container behavior?

e.g.,

instead of

class A
{
     Array!int x;
}

I want

class A
{
    mixin Array!int;
}

so that I can do something like a.Add(3) instead of a.x.Add(3).

In fact, I do want the first case because I will have multiple
arrays and need a way to add separation between them(the x does
that here) BUT the real problem is I need to hook into the add,
remove, etc to do things like validate.

e.g., programming challenge:

Create a class that contains two different arrays of type int and
type float that will restrict the int's to a range of 3 to 10 and
print a msg to the consol when a float larger than 1 is added or
removed from the float array.

a.myints.add(1); // asserts
a.myfloats.add(5); // prints msg to console

myints nor myfloats need to be actual elements of the class. In
fact, in this case it might be ok to override them, e.g.,
a.add(1) and a.add(5f) above.

The goal here is to do this in the minimum amount of work. I
don't want to have to recreate the array code every time I use
them in the class... and I don't want to inherit from a class or
use DI. e.g., templates should be the way to go. Just not sure
how to make it all work and if there are templates that work this
way(allow hooking into the methods).

I thought about using inner classes to add the separation:

class a
{
    class myints // : Array!int
    {
        mixin Array!int;
        // override void Add(int i) {}
    }
}

which I guess would work better if myints was a template.

Any ideas?
February 19, 2014
On Wednesday, 19 February 2014 at 19:10:44 UTC, Frustrated wrote:
> Are there container templates that one can mixin to classes that
> give them container behavior?
>
> e.g.,
>
> instead of
>
> class A
> {
>      Array!int x;
> }
>
> I want
>
> class A
> {
>     mixin Array!int;
> }
>
> so that I can do something like a.Add(3) instead of a.x.Add(3).

One solution is to use alias this.

class A
{
    Array!int x;
    alias x this;
}

Then you can do a.Add(3) and the method call will be "rewritten" (I don't know if it's *actually* rewritten) as a.x.Add(3).

>myints nor myfloats need to be actual elements of the class. In
>fact, in this case it might be ok to override them, e.g.,
>a.add(1) and a.add(5f) above.

This throws a wrench into the above solution, as you can currently only have 1 alias this. However, your idea of inner classes would work, I think.
February 19, 2014
On Wednesday, 19 February 2014 at 19:44:12 UTC, Meta wrote:
> On Wednesday, 19 February 2014 at 19:10:44 UTC, Frustrated wrote:
>> Are there container templates that one can mixin to classes that
>> give them container behavior?
>>
>> e.g.,
>>
>> instead of
>>
>> class A
>> {
>>     Array!int x;
>> }
>>
>> I want
>>
>> class A
>> {
>>    mixin Array!int;
>> }
>>
>> so that I can do something like a.Add(3) instead of a.x.Add(3).
>
> One solution is to use alias this.
>
> class A
> {
>     Array!int x;
>     alias x this;
> }
>
> Then you can do a.Add(3) and the method call will be "rewritten" (I don't know if it's *actually* rewritten) as a.x.Add(3).
>
>>myints nor myfloats need to be actual elements of the class. In
>>fact, in this case it might be ok to override them, e.g.,
>>a.add(1) and a.add(5f) above.
>
> This throws a wrench into the above solution, as you can currently only have 1 alias this. However, your idea of inner classes would work, I think.

yeah, I basically want to avoid typing a lot and reuse code. I
could create a template that is essentially all the code from
your standard container object(probably just rename class to
template) and mix it in. The problem is that there will be a lot
of methods in the class... probably not a real issue. I could use
the types directly. Not sure, though, the benefit of using
templates over inheritance/inner classes.

Just trying to avoid a lot of typing and have an efficient
solution. I have several classes with array inside them and I
want to convert them so that I can add "hooks" later(do stuff
when elements are added/etc easily... without the overhead of
delegates or events that one might normally use for RT behavior).

templates seem like the solution but now sure if there such an
array/container already exists so I can "plug and play".
February 19, 2014
On Wednesday, 19 February 2014 at 19:44:12 UTC, Meta wrote:
> On Wednesday, 19 February 2014 at 19:10:44 UTC, Frustrated wrote:
>> Are there container templates that one can mixin to classes that
>> give them container behavior?
>>
>> e.g.,
>>
>> instead of
>>
>> class A
>> {
>>     Array!int x;
>> }
>>
>> I want
>>
>> class A
>> {
>>    mixin Array!int;
>> }
>>
>> so that I can do something like a.Add(3) instead of a.x.Add(3).
>
> One solution is to use alias this.
>
> class A
> {
>     Array!int x;
>     alias x this;
> }
>
> Then you can do a.Add(3) and the method call will be "rewritten" (I don't know if it's *actually* rewritten) as a.x.Add(3).
>
>>myints nor myfloats need to be actual elements of the class. In
>>fact, in this case it might be ok to override them, e.g.,
>>a.add(1) and a.add(5f) above.
>
> This throws a wrench into the above solution, as you can currently only have 1 alias this. However, your idea of inner classes would work, I think.

I think Proxy would also work here? I'm not sure of the pros/cons of each solution though.
February 19, 2014
On Wednesday, 19 February 2014 at 19:44:12 UTC, Meta wrote:
> On Wednesday, 19 February 2014 at 19:10:44 UTC, Frustrated wrote:
>> Are there container templates that one can mixin to classes that
>> give them container behavior?
>>
>> e.g.,
>>
>> instead of
>>
>> class A
>> {
>>     Array!int x;
>> }
>>
>> I want
>>
>> class A
>> {
>>    mixin Array!int;
>> }
>>
>> so that I can do something like a.Add(3) instead of a.x.Add(3).
>
> One solution is to use alias this.
>
> class A
> {
>     Array!int x;
>     alias x this;
> }
>
> Then you can do a.Add(3) and the method call will be "rewritten" (I don't know if it's *actually* rewritten) as a.x.Add(3).
>
>>myints nor myfloats need to be actual elements of the class. In
>>fact, in this case it might be ok to override them, e.g.,
>>a.add(1) and a.add(5f) above.
>
> This throws a wrench into the above solution, as you can currently only have 1 alias this. However, your idea of inner classes would work, I think.

I played around with it a bit at work and this is a workable solution:

import std.container;

class A
{
	this()
	{
		myints = new MyInts();
		myfloats = new MyFloats();
	}
	
	MyInts myints;
	MyFloats myfloats;
	
	private static
	{
		class MyInts
		{
			Array!int x;
			alias x this;
		}
		
		class MyFloats
		{
			Array!float x;
			alias x this;
		}
	}
}

void main()
{
	auto a = new A();
	a.myints.insert(3);
	a.myfloats.insert(3);
}
February 20, 2014
On Wednesday, 19 February 2014 at 21:50:43 UTC, Meta wrote:
> On Wednesday, 19 February 2014 at 19:44:12 UTC, Meta wrote:
>> On Wednesday, 19 February 2014 at 19:10:44 UTC, Frustrated wrote:
>>> Are there container templates that one can mixin to classes that
>>> give them container behavior?
>>>
>>> e.g.,
>>>
>>> instead of
>>>
>>> class A
>>> {
>>>    Array!int x;
>>> }
>>>
>>> I want
>>>
>>> class A
>>> {
>>>   mixin Array!int;
>>> }
>>>
>>> so that I can do something like a.Add(3) instead of a.x.Add(3).
>>
>> One solution is to use alias this.
>>
>> class A
>> {
>>    Array!int x;
>>    alias x this;
>> }
>>
>> Then you can do a.Add(3) and the method call will be "rewritten" (I don't know if it's *actually* rewritten) as a.x.Add(3).
>>
>>>myints nor myfloats need to be actual elements of the class. In
>>>fact, in this case it might be ok to override them, e.g.,
>>>a.add(1) and a.add(5f) above.
>>
>> This throws a wrench into the above solution, as you can currently only have 1 alias this. However, your idea of inner classes would work, I think.
>
> I played around with it a bit at work and this is a workable solution:
>
> import std.container;
>
> class A
> {
> 	this()
> 	{
> 		myints = new MyInts();
> 		myfloats = new MyFloats();
> 	}
> 	
> 	MyInts myints;
> 	MyFloats myfloats;
> 	
> 	private static
> 	{
> 		class MyInts
> 		{
> 			Array!int x;
> 			alias x this;
> 		}
> 		
> 		class MyFloats
> 		{
> 			Array!float x;
> 			alias x this;
> 		}
> 	}
> }
>
> void main()
> {
> 	auto a = new A();
> 	a.myints.insert(3);
> 	a.myfloats.insert(3);
> }

This should work. Just have to add the overrides and call the
base function(e.g., "override" insert and then call x's insert).

This at least gets the job done... I wonder if there is a better
way?
February 22, 2014
On Thursday, 20 February 2014 at 18:55:06 UTC, Frustrated wrote:
> This should work. Just have to add the overrides and call the
> base function(e.g., "override" insert and then call x's insert).
>
> This at least gets the job done... I wonder if there is a better
> way?

If you want a.Add() (insert() in the case of std.container.Array) to work correctly and be overloaded for both ints and floats, I don't think you have any choice beside implementing it yourself. This is exactly the kind of problem that multiple alias this could solve, but that's not implemented, so I guess you're out of luck. Like you said earlier, however, you can just create a template mixin that mixes in the Array functionality for any type you want, which is about as succint as you're going to get.