www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Array of templated classes or structs

reply Dandyvica <dandyvica gmail.com> writes:
Hi guys,

Apart from deriving from the same class and declaring an array of 
that
root class, is there a way to create an array of templates?

This seems not possible since template are compile-time 
generated, but just to be sure. For example, it seems logical to 
get an array of complex numbers but Complex needs to be declared 
with a type.

Thanks for any hint.
Oct 24 2015
next sibling parent reply qsdfghjk <qsdfghjk niwhere.hj> writes:
On Saturday, 24 October 2015 at 15:57:09 UTC, Dandyvica wrote:
 Hi guys,

 Apart from deriving from the same class and declaring an array 
 of that
 root class, is there a way to create an array of templates?

 This seems not possible since template are compile-time 
 generated, but just to be sure. For example, it seems logical 
 to get an array of complex numbers but Complex needs to be 
 declared with a type.

 Thanks for any hint.
You can declare an array whose the element type matches to one of the template parameter: --- struct Foo(T) { Foo!T[] foos; // typeof(this)[] foos // equivalent } --- since it's an array (fixed size whatever is the element type: size_t len + size_t pointer) it doesn't matter if the template declaration is partial.
Oct 24 2015
parent reply Dandyvica <dandyvica gmail.com> writes:
On Saturday, 24 October 2015 at 16:58:58 UTC, qsdfghjk wrote:
 On Saturday, 24 October 2015 at 15:57:09 UTC, Dandyvica wrote:
 Hi guys,

 Apart from deriving from the same class and declaring an array 
 of that
 root class, is there a way to create an array of templates?

 This seems not possible since template are compile-time 
 generated, but just to be sure. For example, it seems logical 
 to get an array of complex numbers but Complex needs to be 
 declared with a type.

 Thanks for any hint.
You can declare an array whose the element type matches to one of the template parameter: --- struct Foo(T) { Foo!T[] foos; // typeof(this)[] foos // equivalent } --- since it's an array (fixed size whatever is the element type: size_t len + size_t pointer) it doesn't matter if the template declaration is partial.
In that case, all elements have the same type right? I'd like different types, but with the same template.
Oct 24 2015
parent qsdfghjk <qsdfghjk niwhere.hj> writes:
On Saturday, 24 October 2015 at 17:06:13 UTC, Dandyvica wrote:
 On Saturday, 24 October 2015 at 16:58:58 UTC, qsdfghjk wrote:
 On Saturday, 24 October 2015 at 15:57:09 UTC, Dandyvica wrote:
 Hi guys,

 Apart from deriving from the same class and declaring an 
 array of that
 root class, is there a way to create an array of templates?

 This seems not possible since template are compile-time 
 generated, but just to be sure. For example, it seems logical 
 to get an array of complex numbers but Complex needs to be 
 declared with a type.

 Thanks for any hint.
You can declare an array whose the element type matches to one of the template parameter: --- struct Foo(T) { Foo!T[] foos; // typeof(this)[] foos // equivalent } --- since it's an array (fixed size whatever is the element type: size_t len + size_t pointer) it doesn't matter if the template declaration is partial.
In that case, all elements have the same type right? I'd like different types, but with the same template.
Then no, it's not possible, although some ugly workaround may allow the thing (array of pointer and something used to cast the pointer at runtime, like an AliasSeq). But by definition if you have serveral type in an aray it's not array...it's an agregate.
Oct 24 2015
prev sibling parent reply TheFlyingFiddle <kurtyan student.chalmers.se> writes:
On Saturday, 24 October 2015 at 15:57:09 UTC, Dandyvica wrote:
 Hi guys,

 Apart from deriving from the same class and declaring an array 
 of that
 root class, is there a way to create an array of templates?

 This seems not possible since template are compile-time 
 generated, but just to be sure. For example, it seems logical 
 to get an array of complex numbers but Complex needs to be 
 declared with a type.

 Thanks for any hint.
Structs or classes that are templated will create new types each time they are instantiated. struct S(T) { /*stuff*/ } static assert(!is(S!int == S!double)); So you can create arrays of: S!int[] a; or S!double[] b; But you can't really create arrays of S!(int or double)[]. However it can be sort of done by using a variant(taged union). import std.variant; alias SIntOrDouble = Algebraic!(S!int, S!double); SIntOrDouble[] array; array ~= S!int(...); array ~= S!double(...); Now the array holds two items an S!int for the first item and an S!double for the second. You can use it like this. foreach(ref elem; array) { if(auto p = elem.peek!(S!int)) { //Do stuff with an S!int item } else if(auto p = elem.peek!(S!double)) { //Do stuff with an S!double. } } Or like this: foreach(ref elem; array) { elem.visit!( (S!int i) => /*something with ints*/, (S!double d) => /*something with doubles*/ ); } Take a look at std.variant if you are interested. A drawback to the Algebraic is that you must know all the different template instantiations that you will be using. If you don't know this I suggest you use a variant instead. The line: SIntOrDouble[] array; changes to Variant[] array; With this you can hold anything in the array. This is both an advantage and a drawback, the advantage is that you can just add more templpate instantiations to the program as is evolves. But you lose static typing information so the compiler will not be able to help you anymore. For example this would be valid: Variant[] array; array ~= S!int(...); array ~= S!double(...); array ~= S!long(...); array ~= "I am a string!"; And this is probably not what you want.
Oct 24 2015
parent reply TheFlyingFiddle <kurtyan student.chalmers.se> writes:
On Saturday, 24 October 2015 at 18:29:08 UTC, TheFlyingFiddle 
wrote:
 Variant[] array;
 array ~= S!int(...);
 array ~= S!double(...);
 array ~= S!long(...);
 array ~= "I am a string!";

 And this is probably not what you want.
You can do this if you want to ensure that items stored in the variant are of a specific template struct/class. import std.traits, std.variant; struct TemplateStruct(alias template_) { private Varint v; void opAssign(TemplateStruct!template_ other) { this.v = other.v; } void opAssing(T)(T t) if(isInstanceOf!(template_, T)) { this.v = t; } T* peek(T) { return v.peek!T; } auto visit(Handlers...) { return v.visit!handler; } //More variant stuff here. } This should work: (untested) TemplateStruct!(S)[] array; array ~= S!int(...); array ~= S!long(...); array ~= S!double(...); array ~= "I am a string!"; //This line should issue a compiler error. To complete TemplateStruct simply forward the remaing members of the variant. Or use something like proxy!T in std.typecons. Or use an alias this v. (I don't really recommend alias this it has all kinds of problems)
Oct 24 2015
parent reply TheFlyingFiddle <kurtyan student.chalmers.se> writes:
On Saturday, 24 October 2015 at 18:40:02 UTC, TheFlyingFiddle 
wrote:
 To complete TemplateStruct simply forward the remaing members 
 of the
 variant. Or use something like proxy!T in std.typecons. Or use 
 an alias this v.
 (I don't really recommend alias this it has all kinds of 
 problems)
One thing about variant is that if the struct you are trying to insert is larger then (void delegate()).sizeof it will allocate the wrapped type on the gc heap. This might be detrimental to performance. So to help with this you could add an extra element on the TemplateStruct to sort of handle this. struct TemplateStruct(alias template_, size_t size = (void delegate).sizeof) { VariantN!(size) v; //Rest is the same. } Pick a good size for the template you want to make arrays of and it will lessen the stress on the gc heap. For example: struct vec4(T) { T[4] data; //stuff } alias Vector4 = TemplateStruct!(template_, vec4!(double).sizeof); Vector4[] array; Additionaly you might want to look into the (http://forum.dlang.org/thread/jiucsrcvkfdzwinqpzxg forum.dlang.org) if your interested in some cool stuff that can be done to call methods on such variant structs.
Oct 24 2015
parent reply TheFlyingFiddle <kurtyan student.chalmers.se> writes:
On Saturday, 24 October 2015 at 19:00:57 UTC, TheFlyingFiddle 
wrote:
 One thing about variant is that if the struct you are trying to 
 insert is larger then (void delegate()).sizeof it will allocate 
 the wrapped type on the gc heap.
This is not a concern if you want to have class templates as they are on the heap anyways and have a fixed size.
Oct 24 2015
parent Dandyvica <dandyvica gmail.com> writes:
On Saturday, 24 October 2015 at 19:02:50 UTC, TheFlyingFiddle 
wrote:
 On Saturday, 24 October 2015 at 19:00:57 UTC, TheFlyingFiddle 
 wrote:
 One thing about variant is that if the struct you are trying 
 to insert is larger then (void delegate()).sizeof it will 
 allocate the wrapped type on the gc heap.
This is not a concern if you want to have class templates as they are on the heap anyways and have a fixed size.
Thanks TheFlyingFiddle! I've tought to using variants but not that way! Seems an interesting path to follow...
Oct 26 2015