Just came across this issue today. I wanted to create a typical value type wrapper around a heap allocated object. I even created a nice postblit constructor like a good D programmer.

struct Ptr
{
  private int* p;
  this(int x) { p = new int; *p = x; }
  this(this) { int x = *p; p = new int; *p = x; }
  ...
}

void main()
{
  const Ptr a = Ptr(1);
  Ptr b = a; // error
}


Problem is, this code is illegal because you can't create a non-const copy of a const value type that contains pointers or references (due to transitive const).

I can get around it in this particular instance by creating a dup property (like a C++ copy constructor):

struct Ptr
{
  @property const Ptr dup()
  {
    return Ptr(*p);
  }
}

But it still means that my struct is non-copyable in general. For example, I can't fill a range with a const Ptr.

const Ptr a = Ptr(1);
Ptr[10] arr;
std.algorithm.fill(arr[], a); // error


I understand why the shallow copy isn't allowed in general (it would break transitive const), but as the dup property demonstrates, I am able to create a deep copy of Ptr without violating const-correctness -- the problem is that I am not able to express this using a postblit constructor.

Am I missing something? How are you supposed to define value semantics on structs containing pointers?

Reply via email to