www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to structure templated classes

reply =?ISO-8859-1?Q?Christian_K=F6stlin?= <christian.koestlin gmail.com> writes:
I have a templated class that has many (static) inner classes which also 
use the template parameter. e.g.
import std.stdio;

class Test(T) {
   static class Inner1 : Test {
	T h;
   }
   static class Inner2 : Test {
	T h;
   }
}

unittest {
   alias Test!(string) StringTest;
   alias Test!(int) IntTest;

   auto t1 = new StringTest.Inner1();
   auto t2 = new StringTest.Inner1();
   auto t3 = new IntTest.Inner2();
   auto t4 = new IntTest.Inner2();
}

int main(string[] args) {
   return 0;
}

in my real case there are a lot more inner classes (which acutally 
implement the interface defined by the surrounding class).

this is very convenient, because i can create all of the inner classes 
for one type just with an alias. thats what templates are for.

the problem is, i want to pull out the inner classes so that my module 
gets smaller, but then i have to make several aliases to get the desired 
template instances e.g. i would create a module:
class Innert1(T) : Test!(T) {
   T h;
}

and an alias for that like: alias Innert1!(string) StringInner1;

that is very repetitive when i have many of those inner classes.

So the question now is. Is there a way to split the big module in 
several smaller ones, and at the same time keep the possibility to let 
the "template magic" do its work?

thanks in advance

christian
May 09 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-09 22:21, Christian Köstlin wrote:
 I have a templated class that has many (static) inner classes which also
 use the template parameter. e.g.
 import std.stdio;

 class Test(T) {
 static class Inner1 : Test {
 T h;
 }
 static class Inner2 : Test {
 T h;
 }
 }

 unittest {
 alias Test!(string) StringTest;
 alias Test!(int) IntTest;

 auto t1 = new StringTest.Inner1();
 auto t2 = new StringTest.Inner1();
 auto t3 = new IntTest.Inner2();
 auto t4 = new IntTest.Inner2();
 }

 int main(string[] args) {
 return 0;
 }

 in my real case there are a lot more inner classes (which acutally
 implement the interface defined by the surrounding class).

 this is very convenient, because i can create all of the inner classes
 for one type just with an alias. thats what templates are for.

 the problem is, i want to pull out the inner classes so that my module
 gets smaller, but then i have to make several aliases to get the desired
 template instances e.g. i would create a module:
 class Innert1(T) : Test!(T) {
 T h;
 }

 and an alias for that like: alias Innert1!(string) StringInner1;

 that is very repetitive when i have many of those inner classes.

 So the question now is. Is there a way to split the big module in
 several smaller ones, and at the same time keep the possibility to let
 the "template magic" do its work?

 thanks in advance

 christian

Perhaps you can use template mixins (untested). class Test (T) { mixin InnerClasses!(T); } template InnerClasses (T) { static class Inner1 : Test!(T) {} // ... and so on } -- /Jacob Carlborg
May 09 2012
parent reply =?ISO-8859-1?Q?Christian_K=F6stlin?= <christian.koestlin gmail.com> writes:
On 05/09/2012 10:48 PM, Jacob Carlborg wrote:
 Perhaps you can use template mixins (untested).

 class Test (T)
 {
 mixin InnerClasses!(T);
 }

 template InnerClasses (T)
 {
 static class Inner1 : Test!(T) {}
 // ... and so on
 }

thank for your answer, yes .. that could possibly work, but would still force me to add all the mixins to the main class. in addition to that i could not longer use the mixin-classes standalone (i would have to mixin them into the place i want to use them). i think i have to rework my code ... regards christian
May 10 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-10 13:41, Christian Köstlin wrote:

 thank for your answer,

 yes .. that could possibly work, but would still force me to add all the
 mixins to the main class. in addition to that i could not longer use the
 mixin-classes standalone (i would have to mixin them into the place i
 want to use them).

 i think i have to rework my code ...

 regards

 christian

You don't need to mix in the classes. You can access them by: InnerClasses!(T).Inner1 -- /Jacob Carlborg
May 10 2012
parent reply =?ISO-8859-1?Q?Christian_K=F6stlin?= <christian.koestlin gmail.com> writes:
On 05/10/2012 02:13 PM, Jacob Carlborg wrote:
 On 2012-05-10 13:41, Christian Köstlin wrote:

 thank for your answer,

 yes .. that could possibly work, but would still force me to add all the
 mixins to the main class. in addition to that i could not longer use the
 mixin-classes standalone (i would have to mixin them into the place i
 want to use them).

 i think i have to rework my code ...

 regards

 christian

You don't need to mix in the classes. You can access them by: InnerClasses!(T).Inner1

use them directly anymore, which was one motivation to extract them from InnerClasses. Thanks
May 10 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-10 17:39, Christian Köstlin wrote:

 ok .. sure you can use them by the way of InnerClasses, but you cannot
 use them directly anymore, which was one motivation to extract them from
 InnerClasses.

Ah, I missed that. But one mixin isn't that bad? Or do you want to place them in several templates. -- /Jacob Carlborg
May 10 2012
parent =?ISO-8859-1?Q?Christian_K=F6stlin?= <christian.koestlin gmail.com> writes:
On 05/10/2012 06:47 PM, Jacob Carlborg wrote:
 On 2012-05-10 17:39, Christian Köstlin wrote:

 ok .. sure you can use them by the way of InnerClasses, but you cannot
 use them directly anymore, which was one motivation to extract them from
 InnerClasses.

Ah, I missed that. But one mixin isn't that bad? Or do you want to place them in several templates.

when i extracted the classes into seperate modules i liked it really, but then i updated old code that used these classes and one of the files used the alias trick to get all of the inner classes (a usecase which i had forgotten). i was able to work around this problem, but this made me reconsider the last refactoring :) thank again for your solution! christian
May 10 2012