| |
| Posted by Chris Nicholson-Sauls in reply to Daniel Giddings | PermalinkReply |
|
Chris Nicholson-Sauls
Posted in reply to Daniel Giddings
| Daniel Giddings wrote:
> First there seems to be an issue with copying tuples made from structs with .tupleof (sample code in test.d).
>
> > dmd -run test.d
> 12.3
> 0nan
>
> I'm guessing that this is for similar reasons to tuples not being able to be returned from functions yet?
>
> Which brings me to my question re templates... in pack.d I have templated a Tuple struct which can have varying numbers of properties. Is there a way of doing this where you don't have to write out the maximum number of elements manually?
>
> The names aren't important as you can iterate over them with .tupleof.
>
> template Tuple( T... )
> {
> align(1) struct Tuple
> {
> static if( T.length > 0 ) { T[0] first; }
> static if( T.length > 1 ) { T[1] second; }
> static if( T.length > 2 ) { T[2] third; }
> static if( T.length > 3 ) { T[3] fourth; }
> static if( T.length > 4 ) { T[4] fifth; }
> static if( T.length > 5 ) { T[5] sixth; }
> static if( T.length > 6 ) { T[6] seventh; }
> static if( T.length > 7 ) { T[7] eighth; }
> static if( T.length > 8 ) { T[8] ninth; }
> // ... etc if more than 9 elements are needed
> }
> }
>
> Running pack.d produces:
>
> > dmd -run pack.d
> a
> 1
> 2.3
>
> I'm only interested in packing PoD (plain old data types) at this stage.
>
> Cheers,
>
> :-) Dan
>
>
>
> ------------------------------------------------------------------------
>
> import std.stdio;
>
> void main()
> {
> struct S
> {
> int i = 1;
> double j = 2.3;
> }
>
> S s;
>
> writefln( s.tupleof );
>
> auto t = s.tupleof;
>
> writefln( t );
> }
>
>
> ------------------------------------------------------------------------
>
> import std.stdio;
> import std.string;
>
> template Tuple( T... )
> {
> align(1) struct Tuple
> {
> static if( T.length > 0 ) { T[0] first; }
> static if( T.length > 1 ) { T[1] second; }
> static if( T.length > 2 ) { T[2] third; }
> static if( T.length > 3 ) { T[3] fourth; }
> static if( T.length > 4 ) { T[4] fifth; }
> static if( T.length > 5 ) { T[5] sixth; }
> static if( T.length > 6 ) { T[6] seventh; }
> static if( T.length > 7 ) { T[7] eighth; }
> static if( T.length > 8 ) { T[8] ninth; }
> // ... etc if more than 9 elements are needed
> }
> }
>
> byte[] pack(T...)( T tuple )
> {
> int size = 0;
>
> foreach( item; tuple )
> size += item.sizeof;
>
> byte[] result = new byte[size];
>
> int position = 0;
>
> foreach( item; tuple )
> {
> result[position..position+item.sizeof] = (cast(byte*)&item)[0..item.sizeof];
> position += item.sizeof;
> }
>
> return result;
> }
>
> Tuple!(T) unpack(T...)( byte[] data )
> {
> Tuple!(T) result;
>
> assert( data.length == result.sizeof );
>
> result = *(cast(Tuple!(T)*)data.ptr);
>
> return result;
> }
>
> void main()
> {
> byte[] packed = pack!(char,short,float)( 'a', 1, 2.3 );
>
> auto unpacked = unpack!(char,short,float)( packed );
>
> foreach( i; unpacked.tupleof )
> writefln( i );
> }
I did something like the following once:
# struct Foo (T ...) {
# T fields;
# }
And was later able to access the declared fields via an index. Aka:
Foo!(int, int, float, bool) myfoo;
myfoo.fields[0] = 42;
myfoo.fields[2] = 3.14;
The following also worked, if I remember right:
myfoo.fields = Tuple!(42, 25, 3.14, true);
-- Chris Nicholson-Sauls
|