Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
August 31, 2015 Array initialization with Struct templates | ||||
---|---|---|---|---|
| ||||
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. |
August 31, 2015 Re: Array initialization with Struct templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to WhatMeWorry | 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
|
August 31, 2015 Re: Array initialization with Struct templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | 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:
>>
>> 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
>
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()
{}
|
August 31, 2015 Re: Array initialization with Struct templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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:
>> 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 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);
|
August 31, 2015 Re: Array initialization with Struct templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | 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 Davis
Or 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()
{}
|
September 01, 2015 Re: Array initialization with Struct templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel N | 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. |
September 01, 2015 Re: Array initialization with Struct templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to WhatMeWorry | 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)) // Compiler error > ]; 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 |
Copyright © 1999-2021 by the D Language Foundation