On Wednesday, 12 November 2014 at 19:15:24 UTC, John McFarlane wrote:
On Wednesday, 12 November 2014 at 00:31:31 UTC, Jesse Phillips wrote:
On Tuesday, 11 November 2014 at 20:53:51 UTC, John McFarlane wrote:
I'm trying to write a struct template that uses `insertInPlace`. However, it doesn't work with certain template type / compiler combinations. Consider the following:

  import std.range;
  struct S { const int c; }
  S[] a;
  insertInPlace(a, 0, S());

With DMD64 D Compiler v2.066.1, I get the following error:
/usr/include/dmd/phobos/std/array.d(1013): Error: cannot modify struct dest[i] S with immutable members /usr/include/dmd/phobos/std/array.d(1079): Error: template instance std.array.copyBackwards!(S) error instantiating ./d/my_source_file.d(12345): instantiated from here: insertInPlace!(S, S)

I believe DMD is correct here and here is why:

While the function is called "insert" the operation is actually an assignment. DMD initializes all arrays elements to the default value so your array position 0 actually contains an S already. This means the operation is equivalent to

   auto b = S();
   b = S();

Since S is a value type you're actually making a modification 'c' as stored in 'b'. The compiler is unable to prove that there is no other reference to that same memory location (though in this case the variable is on the stack and the modification is local so such knowledge may be possible).

That makes sense. In the case that `c` is a class, do you think I'd have any luck if I made it immutable?
The quick answer is that it doesn't help. DMD still doesn't like me using insertInPlace. This is a little disappointing as immutable is supposed to avoid the need for copying. Then again, I guess that's a compiler - not language - level affordance. Thanks again.


In the short term, could anybody suggest a `static if` expression to determine whether I can copy the type to the satisfaction of `copyBackwards`? I tried isMutable but that didn't seem to work.

Thanks, John

You probably want std.traits.isAssignable

   pragma(msg, isAssignable!(S, S)); // False
That's exactly what I was looking for. Thank you.

Reply via email to