digitalmars.D.learn - Array initialization with Struct templates
- WhatMeWorry (34/34) Aug 30 2015 This seemingly trivial array initialization has caused me hours
- Jonathan M Davis via Digitalmars-d-learn (15/49) Aug 30 2015 VertexData doesn't have a constructor that takes 6 doubles or 6 floats. ...
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (34/93) Aug 30 2015 Additionally, the OP uses the is expression which compares the equality
- Mike Parker (22/63) Aug 30 2015 I would drop chameleon all together and just add the fields
- Daniel N (32/39) Aug 31 2015 Or turn Chameleon into a mixin template.
- WhatMeWorry (61/61) Aug 31 2015 Thanks for all the above suggestions, but after many hour of
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (56/83) Aug 31 2015 (Aside: You don't need that semicolon in D.)
This seemingly trivial array initialization has caused me hours of grief. enum Purpose { POSITIONAL, COLOR_ONLY, COLOR_AND_ALPHA, GENERIC_TRIPLE, GENERIC_QUAD } Purpose purpose; struct Chameleon(T, Purpose p) // template { static if (is (p == POSITIONAL)) { T x, y, z; } else static if (is (p == COLOR_ONLY)) { T r, g, b; } else static if (is (p == COLOR_AND_ALPHA)) { T r, g, b, a; } else static if (is (p == GENERIC_TRIPLE)) { T a, b, c; } else static if (is (p == GENERIC_QUAD)) { T a, b, c, d; } }; struct VertexData { Chameleon!(float, purpose.POSITIONAL) position; Chameleon!(float, purpose.COLOR_ONLY) color; } alias Vert = VertexData; VertexData[] vertices = [ Vert(1.0, 1.0, 1.0, 0.0, 0.0, 0.0) // compiler error here ]; I keep getting: Error: cannot implicitly convert expression (1.00000) of type double to Chameleon!(double, cast(Purpose)0) I even tried Vert(1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f) but it has the exact same error. Any ideas? Thanks in advance.
Aug 30 2015
On Monday, August 31, 2015 04:57:05 WhatMeWorry via Digitalmars-d-learn wrote:This seemingly trivial array initialization has caused me hours of grief. enum Purpose { POSITIONAL, COLOR_ONLY, COLOR_AND_ALPHA, GENERIC_TRIPLE, GENERIC_QUAD } Purpose purpose; struct Chameleon(T, Purpose p) // template { static if (is (p == POSITIONAL)) { T x, y, z; } else static if (is (p == COLOR_ONLY)) { T r, g, b; } else static if (is (p == COLOR_AND_ALPHA)) { T r, g, b, a; } else static if (is (p == GENERIC_TRIPLE)) { T a, b, c; } else static if (is (p == GENERIC_QUAD)) { T a, b, c, d; } }; struct VertexData { Chameleon!(float, purpose.POSITIONAL) position; Chameleon!(float, purpose.COLOR_ONLY) color; } alias Vert = VertexData; VertexData[] vertices = [ Vert(1.0, 1.0, 1.0, 0.0, 0.0, 0.0) // compiler error here ]; I keep getting: Error: cannot implicitly convert expression (1.00000) of type double to Chameleon!(double, cast(Purpose)0) I even tried Vert(1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f) but it has the exact same error. Any ideas? Thanks in advance.VertexData doesn't have a constructor that takes 6 doubles or 6 floats. It has a compiler-generated constructor that's equivalent to this(Chameleon!(float, purpose.POSITIONAL) position, Chameleon!(float, purpose.COLOR_ONLY) color) { this.position = position; this.color = color; } So, you're going to need to pass it a Chameleon!(float, purpose.POSITIONAL) and a Chameleon!(float, purpose.COLOR_ONLY color), not 6 doubles - either that, or you're going to need to declare a constructor for VertexData which takes 6 doubles or floats and converts them to what's require to assign to its member variables. - Jonathan M Davis
Aug 30 2015
On 08/30/2015 10:38 PM, Jonathan M Davis via Digitalmars-d-learn wrote:On Monday, August 31, 2015 04:57:05 WhatMeWorry via Digitalmars-d-learn wrote:Additionally, the OP uses the is expression which compares the equality of types. However, 'Purpose p' is a value template parameter. A simple == comparison works: enum Purpose { POSITIONAL, COLOR_ONLY, COLOR_AND_ALPHA, GENERIC_TRIPLE, GENERIC_QUAD } Purpose purpose; struct Chameleon(T, Purpose p) // template { static if (p == Purpose.POSITIONAL) { // <-- NOT is expression T x, y, z; } else static if (p == Purpose.COLOR_ONLY) { T r, g, b; } else static if (p == Purpose.COLOR_AND_ALPHA) { T r, g, b, a; } else static if (p == Purpose.GENERIC_TRIPLE) { T a, b, c; } else static if (p == Purpose.GENERIC_QUAD) { T a, b, c, d; } }; struct VertexData { Chameleon!(float, purpose.POSITIONAL) position; Chameleon!(float, purpose.COLOR_ONLY) color; } alias Vert = VertexData; VertexData[] vertices = [ Vert(Chameleon!(float, purpose.POSITIONAL)(1.0f, 1.0f, 1.0f), Chameleon!(float, purpose.COLOR_ONLY)(0.0, 0.0, 0.0)) ]; void main() {}This seemingly trivial array initialization has caused me hours of grief. enum Purpose { POSITIONAL, COLOR_ONLY, COLOR_AND_ALPHA, GENERIC_TRIPLE, GENERIC_QUAD } Purpose purpose; struct Chameleon(T, Purpose p) // template { static if (is (p == POSITIONAL)) { T x, y, z; } else static if (is (p == COLOR_ONLY)) { T r, g, b; } else static if (is (p == COLOR_AND_ALPHA)) { T r, g, b, a; } else static if (is (p == GENERIC_TRIPLE)) { T a, b, c; } else static if (is (p == GENERIC_QUAD)) { T a, b, c, d; } }; struct VertexData { Chameleon!(float, purpose.POSITIONAL) position; Chameleon!(float, purpose.COLOR_ONLY) color; } alias Vert = VertexData; VertexData[] vertices = [ Vert(1.0, 1.0, 1.0, 0.0, 0.0, 0.0) // compiler error here ]; I keep getting: Error: cannot implicitly convert expression (1.00000) of type double to Chameleon!(double, cast(Purpose)0) I even tried Vert(1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f) but it has the exact same error. Any ideas? Thanks in advance.VertexData doesn't have a constructor that takes 6 doubles or 6 floats. It has a compiler-generated constructor that's equivalent to this(Chameleon!(float, purpose.POSITIONAL) position, Chameleon!(float, purpose.COLOR_ONLY) color) { this.position = position; this.color = color; } So, you're going to need to pass it a Chameleon!(float, purpose.POSITIONAL) and a Chameleon!(float, purpose.COLOR_ONLY color), not 6 doubles - either that, or you're going to need to declare a constructor for VertexData which takes 6 doubles or floats and converts them to what's require to assign to its member variables. - Jonathan M Davis
Aug 30 2015
On Monday, 31 August 2015 at 05:47:31 UTC, Ali Çehreli wrote:On 08/30/2015 10:38 PM, Jonathan M Davis via Digitalmars-d-learn wrote:I would drop chameleon all together and just add the fields directly to VertexData, but make Purpose flag-based. enum Purpose { position = 0x00, // Assuming all verts have a position colorOnly = 0x01, colorAlpha = 0x02, triple = 0x04, quad = 0x08 } enum hasColorOnly(Purpose p) = (p & Purpose.colorOnly) == Purpose.colorOnly; struct VertexData(T, Purpose purpose){ T x, y, z; static if(hasColorOnly!purpose) T r, g, b; ... } Then you can templatize your batches or meshes, or whatever you use to represent vertex objects, on the VertexData type. alias ColorVertexf = VertexData!(float, Purpose.colorOnly); auto batch = new Batch!(ColorVertexf);On Monday, August 31, 2015 04:57:05 WhatMeWorry via Digitalmars-d-learn wrote:This seemingly trivial array initialization has caused me hours of grief. enum Purpose { POSITIONAL, COLOR_ONLY, COLOR_AND_ALPHA, GENERIC_TRIPLE, GENERIC_QUAD } Purpose purpose; struct Chameleon(T, Purpose p) // template { static if (is (p == POSITIONAL)) { T x, y, z; } else static if (is (p == COLOR_ONLY)) { T r, g, b; } else static if (is (p == COLOR_AND_ALPHA)) { T r, g, b, a; } else static if (is (p == GENERIC_TRIPLE)) { T a, b, c; } else static if (is (p == GENERIC_QUAD)) { T a, b, c, d; } }; struct VertexData { Chameleon!(float, purpose.POSITIONAL) position; Chameleon!(float, purpose.COLOR_ONLY) color; } alias Vert = VertexData; VertexData[] vertices = [ Vert(1.0, 1.0, 1.0, 0.0, 0.0, 0.0) // compiler error here ];
Aug 30 2015
On Monday, 31 August 2015 at 05:38:54 UTC, Jonathan M Davis wrote:So, you're going to need to pass it a Chameleon!(float, purpose.POSITIONAL) and a Chameleon!(float, purpose.COLOR_ONLY color), not 6 doubles - either that, or you're going to need to declare a constructor for VertexData which takes 6 doubles or floats and converts them to what's require to assign to its member variables. - Jonathan M DavisOr turn Chameleon into a mixin template. enum Purpose { POSITIONAL, COLOR_ONLY, COLOR_AND_ALPHA, GENERIC_TRIPLE, GENERIC_QUAD } Purpose purpose; mixin template Chameleon(T, Purpose p) // mixin template { static if (p == Purpose.POSITIONAL) { // <-- NOT is expression T x, y, z; } else static if (p == Purpose.COLOR_ONLY) { T r, g, b; } else static if (p == Purpose.COLOR_AND_ALPHA) { T r, g, b, a; } else static if (p == Purpose.GENERIC_TRIPLE) { T a, b, c; } else static if (p == Purpose.GENERIC_QUAD) { T a, b, c, d; } }; struct VertexData { mixin Chameleon!(float, purpose.POSITIONAL) position; mixin Chameleon!(float, purpose.COLOR_ONLY) color; } alias Vert = VertexData; VertexData[] vertices = [ Vert(1.0f, 1.0f, 1.0f, 0.0, 0.0, 0.0), ]; void main() {}
Aug 31 2015
Thanks for all the above suggestions, but after many hour of re-reading Ali's book on template, structs, and mixins, I still in the woods. I've tried two approaches: ================ Templatetized struct ================================ struct Chameleon(T, Purpose p) { static if (p == Purpose.POSITIONAL) { struct Positional { T x, y, z; } } else static if (p == Purpose.COLOR) { struct Color_No_Alpha { T r, g, b; } } }; struct VertexData { Chameleon!(float, purpose.POSITIONAL) position; Chameleon!(float, purpose.COLOR) color; } alias Vert = VertexData; alias Pos = VertexData.position; alias RGB = VertexData.color; VertexData[] vertices = [ VertexData( Pos(1.0, 1.0, 1.0), RGB(0.0, 0.0, 0.0)) // Compiler error ]; Error: struct Chameleon does not overload () Is this the overloading of the default constructor? Can't I use it? I'm I calling it incorrectly? ====================== The Mixin Template approach =========================== mixin template Chameleon(T, Purpose p) { static if (p == Purpose.POSITIONAL) { struct Positional { T x, y, z; } } else static if (p == Purpose.COLOR) { struct Color_No_Alpha { T r, g, b; } } }; struct VertexData { mixin Chameleon!(float, purpose.POSITIONAL) position; mixin Chameleon!(float, purpose.COLOR) color; } alias Vert = VertexData; alias Pos = VertexData.position; alias RGB = VertexData.color; VertexData[] vertices = [ VertexData( Pos(1.0, 1.0, 1.0), RGB(0.0, 0.0, 0.0)) ]; returns Error: function expected before (), not mixin Chameleon!(float, cast(Purpose)0) position; And like above, I'm clueless.
Aug 31 2015
On 08/31/2015 08:55 PM, WhatMeWorry wrote:Thanks for all the above suggestions, but after many hour of re-reading Ali's book on template, structs, and mixins, I still in the woods. I've tried two approaches: ================ Templatetized struct ================================ struct Chameleon(T, Purpose p) { static if (p == Purpose.POSITIONAL) { struct Positional { T x, y, z; } } else static if (p == Purpose.COLOR) { struct Color_No_Alpha { T r, g, b; } } };(Aside: You don't need that semicolon in D.) So, you have a struct template that contains another struct type, either a Positional or a Color_No_Alpha. Note that the outer struct has no members at all: It merely defines two struct types. I can do the following but I don't think it's what you want: auto x = Chameleon!(float, Purpose.POSITIONAL).Positional(1.5, 2.5, 3.5);struct VertexData { Chameleon!(float, purpose.POSITIONAL) position; Chameleon!(float, purpose.COLOR) color; }You have a couple of typos there: purpose should be capitalized. However, I see that you had the following in your original code: enum Purpose { POSITIONAL, COLOR_ONLY, COLOR_AND_ALPHA, GENERIC_TRIPLE, GENERIC_QUAD } Purpose purpose; // ... Chameleon!(float, purpose.POSITIONAL) position; I am surprised that it works! Must be a "feature". ;) The common thing to do is to remove the 'purpose' variable and use the enum type directly: enum Purpose { /* ... */ } // ... Chameleon!(float, Purpose.POSITIONAL) position;alias Vert = VertexData;Fine.alias Pos = VertexData.position; alias RGB = VertexData.color;Those two don't make sense because both .position and .color are member variables. If you did the following, then we would be talking about the types of those members: alias Pos = typeof(VertexData.position); alias RGB = typeof(VertexData.color);VertexData[] vertices = [ VertexData( Pos(1.0, 1.0, 1.0), RGB(0.0, 0.0, 0.0)) // Compilererror];However, that won't work because Chameleon does not have any members. The same with the mixin template... I am copying my earlier code with a couple of aliases to make closer to yours: enum Purpose { POSITIONAL, COLOR_ONLY } struct Chameleon(T, Purpose p) { static if (p == Purpose.POSITIONAL) { T x, y, z; } else static if (p == Purpose.COLOR_ONLY) { T r, g, b; } else { static assert(false, "Not yet supported"); } } alias Pos = Chameleon!(float, Purpose.POSITIONAL); alias Color = Chameleon!(float, Purpose.COLOR_ONLY); struct VertexData { Pos position; Color color; } alias Vert = VertexData; VertexData[] vertices = [ Vert(Pos(1.0f, 1.0f, 1.0f), Color(0.0, 0.0, 0.0)) ]; void main() {} Ali
Aug 31 2015