www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Confused by struct constructors

reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
In attempting to create a function to initialize any array of structs in a  
simple manner, I created this code:

void fillArr( uint n, T, U... )( ref T[] arr, U args ) {
   arr[0] = T( U[0..n] );
   static if ( U.length > n ) {
     fillArr!( n )( arr[ 1..$ ], args[ n..$ ] );
   }
}

T[] initArray( T, uint n = U.length, U... )( U args ) if ( n > 0 ) {
   static if (
//      ( __traits( compiles, T( args[ 0..n ] ) ) ) && // Same as below.  
Added for completeness.
       ( is( typeof( T( args[ 0..n ] ) ) ) ) &&  // If we can instantiate a  
struct with this
       ( U.length % n == 0 )                     // and it matches the  
number of arguments,
       ) {
     T[] result = new T[ U.length / n ];         // Create an array
     fillArr!( n )( result, args );              // and fill it.
     return result;
   } else {
     return initArray!( T, n-1, U )( args );     // Didn't work. Try  
another parameter count.
   }
}

However, upon testing it with this code:

struct S {
   int n;
   string s;
}
auto s = initArray!( S )( 1, "a", 2, "b", 3, "c" );

I get this error:

foo.d(34): Error: cannot implicitly convert expression ((int _param_1,  
string _param_2)) of type (int _param_1, string _param_2) to int


The problem is apparently on this line:
   arr[0] = T( U[0..n] );
Though I am confuzzled as to why it does not work ( it works in initArray,  
line 2 ). Any ideas?

-- 
Simen
Jan 23 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Simen kjaeraas:

 In attempting to create a function to initialize any array of structs in a  
 simple manner,
 ...
 auto s = initArray!( S )( 1, "a", 2, "b", 3, "c" );
That syntax is not useful, if you have few more structs or fields you are lost in the soup of commas and items.. Bye, bearophile
Jan 23 2010
prev sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sat, Jan 23, 2010 at 14:44, Simen kjaeraas <simen.kjaras gmail.com>wrote:

 In attempting to create a function to initialize any array of structs in a
 simple manner, I created this code:

 void fillArr( uint n, T, U... )( ref T[] arr, U args ) {
  arr[0] = T( U[0..n] );
  static if ( U.length > n ) {
    fillArr!( n )( arr[ 1..$ ], args[ n..$ ] );
  }
 }
U is a type . U[0..n] is also a type. You should write: arr[0] = T(args[0..n]); Maybe you could also use S.tupleof.length to get the number of fields in S (or maybe there is a __traits which gives this) and avoid the recursion in initArray: void fillArr( T, U... )( ref T[] arr, U args ) { arr[0] = T(args[0..T.tupleof.length]) ; static if ( U.length > T.tupleof.length ) { fillArr( arr[ 1..$ ], args[ T.tupleof.length..$ ] ); } } T[] initArray( T, U... )( U args ) if ( U.length > 0 && (is(typeof( T( args[ 0..T.tupleof.length ] ) ) ) ) && ( U.length % T.tupleof.length == 0 )) { T[] result = new T[ U.length / T.tupleof.length ]; // Create an array fillArr( result, args ); // and fill it. return result; } Philippe
Jan 23 2010
parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
On Sat, 23 Jan 2010 18:09:26 +0100, Philippe Sigaud  =

<philippe.sigaud gmail.com> wrote:

 On Sat, Jan 23, 2010 at 14:44, Simen kjaeraas  =
 <simen.kjaras gmail.com>wrote:

 In attempting to create a function to initialize any array of structs=
=
 in a
 simple manner, I created this code:

 void fillArr( uint n, T, U... )( ref T[] arr, U args ) {
  arr[0] =3D T( U[0..n] );
  static if ( U.length > n ) {
    fillArr!( n )( arr[ 1..$ ], args[ n..$ ] );
  }
 }
U is a type . U[0..n] is also a type. You should write:
Thank you! Darn, I should have been able to see that.
 Maybe you could also use S.tupleof.length to get the number of fields =
in =
 S
Yeah, I could. However, S might use a different constructor, taking a different number of arguments. As for bearophile's concerns: struct simpleTuple( T... ) { T payload; } simpleTuple!( T ) =E0=BA=95( T... )( T args ) { return simpleTuple!( args ); } T[] initArray( T, U... )( U args ) if ( is( typeof( T( args[0].tupleo= f ) = ) ) && allSame!( U ) ) { T[] result =3D new T[ U.length ]; foreach ( i, arg; args ) { result[ i ] =3D T( arg.tupleof ); } return result; } struct S { int n; string s; } auto s =3D initArray!( S )( =E0=BA=95( 1, "a" ), =E0=BA=95( 2, "b" ),= =E0=BA=95( 3, "c" ) ); If =E0=BA=95 is too hard to type, choose another short name. -- = Simen
Jan 23 2010
parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
 auto s =3D initArray!( S )( =E0=BA=95( 1, "a" ), =E0=BA=95( 2, "b" ), =E0=
=BA=95( 3, "c" ) );

 If =E0=BA=95 is too hard to type, choose another short name.
Nice looking character. Indian, hebrew? When I want an almost non-visible char, I tend tu use _, just _. Philippe
Jan 23 2010