July 29, 2013
> Fixed, thanks. I wasn't sure if the post was ready for Reddit, as it's mainly some thoughts written down for advanced D users.

Thanks for writing this. Aside from the primary purpose of the article, I was able to learn along the way more about D's mixins because of it.

As a game architect, I love discovering ways to further abstract, reuse, improve speed, and aid readability... all stuff that mixins can help with. ;)
July 30, 2013
On 28-7-2013 08:20, Vladimir Panteleev wrote:
> Not really an article or anything - this was planned as just a post to
> this newsgroup, but I decided to put it somewhere suitable for larger
> blocks of text with formatting:
>
> http://blog.thecybershadow.net/2013/07/28/low-overhead-components/

I do not understand what this code should help with:

struct LAYER(BASE)
{
    BASE base;
    // ... use base ...
}

Any advice on what I should read to get it?
(no C++ exp)
July 30, 2013
On Tuesday, 30 July 2013 at 12:37:26 UTC, Faux Amis wrote:
> I do not understand what this code should help with:
>
> struct LAYER(BASE)
> {
>     BASE base;
>     // ... use base ...
> }
>
> Any advice on what I should read to get it?
> (no C++ exp)

It is meant to do "has-a" (http://en.wikipedia.org/wiki/Has-a) inheritance with only exception - it should not be as is not an inheritance. :) Common way to achieve code re-usage without defining meaningless hierarchies.
July 30, 2013
On Sunday, 28 July 2013 at 06:20:29 UTC, Vladimir Panteleev wrote:
> Not really an article or anything - this was planned as just a post to this newsgroup, but I decided to put it somewhere suitable for larger blocks of text with formatting:
>
> http://blog.thecybershadow.net/2013/07/28/low-overhead-components/

On topic of proposals: what to you think about embedding context pointer into struct when such alias is used? That will require some enforcement from compiler if template instance will be actually used as member field in same struct but avoid template bloat and fits with existing behavior of nested aggregates.
July 30, 2013
On Tuesday, 30 July 2013 at 13:28:40 UTC, Dicebot wrote:
> On Sunday, 28 July 2013 at 06:20:29 UTC, Vladimir Panteleev wrote:
>> Not really an article or anything - this was planned as just a post to this newsgroup, but I decided to put it somewhere suitable for larger blocks of text with formatting:
>>
>> http://blog.thecybershadow.net/2013/07/28/low-overhead-components/
>
> On topic of proposals: what to you think about embedding context pointer into struct when such alias is used? That will require some enforcement from compiler if template instance will be actually used as member field in same struct but avoid template bloat and fits with existing behavior of nested aggregates.

While not a bad proposal in itself, it's not very interesting in terms of performance. If we are to do pointers, then pointers to the lower layer aren't much harder to do by hand and save you the ECX (this pointer) adjustment when calling the lower layer's methods.
July 30, 2013
On 30-7-2013 14:48, Dicebot wrote:
> On Tuesday, 30 July 2013 at 12:37:26 UTC, Faux Amis wrote:
>> I do not understand what this code should help with:
>>
>> struct LAYER(BASE)
>> {
>>     BASE base;
>>     // ... use base ...
>> }
>>
>> Any advice on what I should read to get it?
>> (no C++ exp)
>
> It is meant to do "has-a" (http://en.wikipedia.org/wiki/Has-a)
> inheritance with only exception - it should not be as is not an
> inheritance. :) Common way to achieve code re-usage without defining
> meaningless hierarchies.

like this:?

struct LAYER(BASE)
{
	BASE base;
	// ... use base ...
	void func(){};
}

struct Base
{
	alias LAYER!(Base) Layer;
	Layer layer;
	layer.base = this;
	layer.func();
    // ...
}
July 30, 2013
On Tuesday, 30 July 2013 at 14:21:55 UTC, Vladimir Panteleev wrote:
> While not a bad proposal in itself, it's not very interesting in terms of performance. If we are to do pointers, then pointers to the lower layer aren't much harder to do by hand and save you the ECX (this pointer) adjustment when calling the lower layer's methods.

My guess (guess!) it will actually have better performance than generating new template body for every member field. That template bloat can easily get out of control to the point of negative performance impact. As I have already mentioned, we don't do that for nested aggregates - and this one is not that different.

I do favor you first proposal actually but it requires some considerations about fitting concept into language design (despite being easy to implement).
July 30, 2013
On Tuesday, 30 July 2013 at 14:33:59 UTC, Faux Amis wrote:
> like this:?
>
> struct LAYER(BASE)
> {
> 	BASE base;
> 	// ... use base ...
> 	void func(){};
> }
>
> struct Base
> {
> 	alias LAYER!(Base) Layer;
> 	Layer layer;
> 	layer.base = this;
> 	layer.func();
>     // ...
> }

Not quite.

Let's say that, for the sake of example, we want to create a pipeline for doing simple operations for integers using this technique.

First, let's define an interface by convention. Each layer will have a method that handles the int value. Let's call that method "process". It will take one int argument and return void.

So, one layer to add 1 to the result and pass it to the next layer would look like this:

struct Incrementer(BASE)
{
	BASE next;

	void process(int value)
	{
		next.process(value + 1);
	}
}

If we want to multiply numbers by 2, same thing:

struct Doubler(BASE)
{
	BASE next;

	void process(int value)
	{
		next.process(value * 2);
	}
}

At the end of the chain, we'll want to save or print the result. This layer does not have a BASE, so it doesn't even need to be a template:

struct Printer
{
	void process(int value)
	{
		writeln(value);
	}
}

And here's how to use everything together, if we want to print x*2+1:

import std.stdio;

alias Printer Layer0;
alias Incrementer!Layer0 Layer1;
alias Doubler!Layer1 Layer2;

void main()
{
	Layer2 chain;
	chain.process(3); // will print 7
}
July 30, 2013
On Sunday, 28 July 2013 at 21:03:43 UTC, Vladimir Panteleev wrote:
> Why? The difference is one indirection. Are you referring to the impact of template bloat and code cache misses?

bloat

> Yes, but you still need to write it.

That's what we do.
You need to write it anyway to provide simple interface to load xml files, no matter whether you use mixins or nesting.

> With mixins, each layer is declared separately, and you can access it directly.

Don't you fear namespace pollution? You probably don't want to call arbitrary methods on xmlParser and later try to figure out, what did you call exactly.
July 30, 2013
On 30-7-2013 17:22, Vladimir Panteleev wrote:
> On Tuesday, 30 July 2013 at 14:33:59 UTC, Faux Amis wrote:
>> like this:?
>>
>> struct LAYER(BASE)
>> {
>>     BASE base;
>>     // ... use base ...
>>     void func(){};
>> }
>>
>> struct Base
>> {
>>     alias LAYER!(Base) Layer;
>>     Layer layer;
>>     layer.base = this;
>>     layer.func();
>>     // ...
>> }
>
> Not quite.
>
> Let's say that, for the sake of example, we want to create a pipeline
> for doing simple operations for integers using this technique.
>
> First, let's define an interface by convention. Each layer will have a
> method that handles the int value. Let's call that method "process". It
> will take one int argument and return void.
>
> So, one layer to add 1 to the result and pass it to the next layer would
> look like this:
>
> struct Incrementer(BASE)
> {
>      BASE next;
>
>      void process(int value)
>      {
>          next.process(value + 1);
>      }
> }
>
> If we want to multiply numbers by 2, same thing:
>
> struct Doubler(BASE)
> {
>      BASE next;
>
>      void process(int value)
>      {
>          next.process(value * 2);
>      }
> }
>
> At the end of the chain, we'll want to save or print the result. This
> layer does not have a BASE, so it doesn't even need to be a template:
>
> struct Printer
> {
>      void process(int value)
>      {
>          writeln(value);
>      }
> }
>
> And here's how to use everything together, if we want to print x*2+1:
>
> import std.stdio;
>
> alias Printer Layer0;
> alias Incrementer!Layer0 Layer1;
> alias Doubler!Layer1 Layer2;
>
> void main()
> {
>      Layer2 chain;
>      chain.process(3); // will print 7
> }

Thanks!

For teaching purposes I would suggest to make the flow more obvious by writing it like this:

struct Incrementer(BASE)
{
    BASE next;

    void process(int value)
    {
        value += 1;
        next.process(value);
    }
}