Thread overview
heap allocate empty S with variadic ctor
Nov 04, 2012
Dan
Nov 04, 2012
Tobias Pankrath
Nov 04, 2012
Dan
November 04, 2012
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();
}

November 04, 2012
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([]);


November 04, 2012
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!