digitalmars.D.learn - Array of templated classes or structs
- Dandyvica (9/9) Oct 24 2015 Hi guys,
- qsdfghjk (13/22) Oct 24 2015 You can declare an array whose the element type matches to one of
- Dandyvica (4/29) Oct 24 2015 In that case, all elements have the same type right? I'd like
- qsdfghjk (5/37) Oct 24 2015 Then no, it's not possible, although some ugly workaround may
- TheFlyingFiddle (56/65) Oct 24 2015 Structs or classes that are templated will create new types each
- TheFlyingFiddle (33/39) Oct 24 2015 You can do this if you want to ensure that items stored in the
- TheFlyingFiddle (25/31) Oct 24 2015 One thing about variant is that if the struct you are trying to
- TheFlyingFiddle (4/7) Oct 24 2015 This is not a concern if you want to have class templates as they
- Dandyvica (5/12) Oct 26 2015 Thanks TheFlyingFiddle! I've tought to using variants but not
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
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
On Saturday, 24 October 2015 at 16:58:58 UTC, qsdfghjk wrote:On Saturday, 24 October 2015 at 15:57:09 UTC, Dandyvica wrote:In that case, all elements have the same type right? I'd like different types, but with the same template.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
On Saturday, 24 October 2015 at 17:06:13 UTC, Dandyvica wrote:On Saturday, 24 October 2015 at 16:58:58 UTC, qsdfghjk wrote: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.On Saturday, 24 October 2015 at 15:57:09 UTC, Dandyvica wrote:In that case, all elements have the same type right? I'd like different types, but with the same template.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
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
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
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
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
On Saturday, 24 October 2015 at 19:02:50 UTC, TheFlyingFiddle wrote:On Saturday, 24 October 2015 at 19:00:57 UTC, TheFlyingFiddle wrote:Thanks TheFlyingFiddle! I've tought to using variants but not that way! Seems an interesting path to follow...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 26 2015