www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - heap allocate empty S with variadic ctor

reply "Dan" <dbdavidson yahoo.com> writes:
This may be a manifestation of bug 1528. In the code below how 
can I heap allocate a default S? I can't seem to get a call to 
work.

In general structs are stack objects, but is there any problem 
with using the heap to get one?

Thanks
Dan

----------------------------------
import std.stdio;
import std.traits;

struct T { int t; }
struct S {
   T[] ts;

   this(U)(U[] values...) if (isImplicitlyConvertible!(U, T)) {
     foreach (value; values) {
       ts ~= value;
     }
   }
   this(this) {
     ts = ts.dup;
   }
}

void main() {
   S s2;
   S s = S(T(1), T(2), T(3));
   S *sp = new S(T(8));         // fine
   S *sp2 = new S([T(2430)]);   // fine
   // No: template thisstuff.S.__ctor does not match any function 
template declaration
   // S *sp3 = new S;
   // Same - here but also 'no constructor for S'
   // S sp3 = new S([]);
   // Same
   // S sp3 = new S();
}
Nov 04 2012
parent reply Tobias Pankrath <lists pankrath.net> writes:
On 04.11.2012 13:58, Dan wrote:
 This may be a manifestation of bug 1528. In the code below how can I
 heap allocate a default S? I can't seem to get a call to work.

 In general structs are stack objects, but is there any problem with
 using the heap to get one?
No, you can get one, but op new returns a pointer to the struct on the heap. Furthermore if you define your own constructor, your struct will not have an no arg constructor anymore.
 ----------------------------------
 import std.stdio;
 import std.traits;

 struct T { int t; }
 struct S {
    T[] ts;

    this(U)(U[] values...) if (isImplicitlyConvertible!(U, T)) {
      foreach (value; values) {
        ts ~= value;
      }
    }
    this(this) {
      ts = ts.dup;
    }
 }

 void main() {

    // S *sp3 = new S; // no no-aro constructor
    // Same - here but also 'no constructor for S'

    // S sp3 = new S([]); // you forgot the *.
    // this works:
    // S* sp3 = new S(cast(T[])[]);
Sadly you have to cast, because typeof([]) is void[]. Alternatively you could define an constructor that takes void[] but insists of the argument being empty.
    // Same
    // S sp3 = new S(); // no no-arg constructor and no *
 }
struct S { T[] ts; this(U)(U[] values...) if (isImplicitlyConvertible!(U, T) && !is(U == void)) { foreach (value; values) { ts ~= value; } } // extra constructor for [] this(U)(U[] values) if(is(U == void)) { enforce(values.length == 0); } this(this) { ts = ts.dup; } } // works now too. S* s = new S([]);
Nov 04 2012
parent "Dan" <dbdavidson yahoo.com> writes:
On Sunday, 4 November 2012 at 19:30:49 UTC, Tobias Pankrath wrote:
 Sadly you have to cast, because typeof([]) is void[]. 
 Alternatively you could define an constructor that takes void[] 
 but insists of the argument being empty.
Great explanation - thanks!
Nov 04 2012